8

So with this api that I’m using I often encounter json containing a field that is either an array or an object, and I’m not sure how to deal with this the right way.

What happens is that I have an array in my json which is

  • an empty array if there are no entries
  • an array of objects when there are more than one entries
  • actually not an array but an object when there is exactly one entry.

Here is an example to make things clearer:

none:

{
    "what": "kittens",
    "why": "I don't meow",
    "kittens": []
}

one:

{
    "what": "kittens",
    "why": "I don't meow",
    "kittens": {
        "name": "Ser Pounce",
        "gender": "male"
    }
}

many:

{
    "what": "kittens",
    "why": "I don't meow",
    "kittens": [
        {
            "name": "Ser Pounce",
            "gender": "male"
        },
        {
            "name": "Mr. Snuffles",
            "gender": "male"
        }
    ]
}

Now, if this wasn't the case and the second example looked like this

{
    "what": "kittens",
    "why": "I don't meow",
    "kittens": [
        {
            "name": "Ser Pounce",
            "gender": "male"
        }
    ]
}

I could just use a POJO

public class Kittens
{
    public String what;
    public String why;
    public List<Kitten> kittens;

    public static class Kitten
    {
        public String name;
        public String gender;
    }
}

and then deserialize everything the standard way:

Kittens kittens = objectMapper.readValue(good_kitten, Kittens.class);

So an alternative would be using the tree model and doing a lot of type checking manually (with JsonNode.isArray() etc.)

That wouldn't be viable though because there would be a lot of overhead, it wouldn't be elegant and did I mention there's also some nesting going on of course:

{
    "what": "kittens",
    "why": "I don't meow",
    "kittens": [
        {
            "name": "Ser Pounce",
            "gender": "male",
            "kittens": []
        },
        {
            "name": "Mr. Snuffles",
            "gender": "male",
            "kittens": {
                "name": "Waffles",
                "gender": "female",
                "kittens": [
                    {
                        "name": "Mittens",
                        "gender": "male",
                        "kittens": []
                    },
                    {
                        "name": "Winston",
                        "gender": "male",
                        "kittens": {
                            "name": "Fiona",
                            "gender": "female",
                            "kittens": []
                        }
                    }
                ]
            }
        }
    ]
}

Now I would really like to define a model like the following and be done with it

public class NestedKittens
{
    public String what;
    public String why;
    public List<Kitten> kittens;

    public static class Kitten
    {
        public String name;
        public String gender;
        public List<Kitten> kittens;
    }
}

But this won't work because in the json there are Plain Old Kitten Objects where there should be List<Kitten>.

So, are there any annotations or configurations available that make jackson convert from Kitten to List<Kitten> automagically when it needs to?

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
florian
  • 434
  • 2
  • 12

1 Answers1

12

The solution turned out to be really simple:

objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
florian
  • 434
  • 2
  • 12