skip to Main Content

I’m trying to use ObjectMapper to deserialize json but got some problem. Probably what I want is not possible with ObjectMapper but I will ask anyway for a good approach. Let’ say I have a class with the list of objects like this:

public class SomeClass {

    ArrayList<BaseClass> list;
}
public class BaseClass {
    String id;
    String type;
}
public class MyClass1 extends BaseClass{

}
public class MyClass2 extends BaseClass{

}

And a json like this:

{
    "list": [
      {
        "id": "1",
        "type": "MyClass1",
      },
      {
        "id": "2",
        "type": "MyClass2",
      },
      {
        "id": "3",
        "type": "MyClass1",
      }
    ]
}

The question is how to tell ObjectMapper to create and put to the list not a BaseClass objects but MyClass1, MyClass2... objects depends on the value of "type"? Is that possible?

3

Answers


  1. You may try to create a customer Mapper, something like:

    public class CustomDeserializer extends JsonDeserializer<BaseClass> {
        @Override
        public BaseClass deserialize(JsonParser jp, DeserializationContext ctxt) 
          throws IOException, JsonProcessingException {
            ObjectCodec oc = jp.getCodec();
            JsonNode node = oc.readTree(jp);
            String type = node.get("type").asText();
            String id = node.get("id").asText();
            
            if ("MyClass1".equals(type)) {
                MyClass1 myClass1 = new MyClass1();
                myClass1.id = id;
                myClass1.type = type;
                return myClass1;
            } else if ("MyClass2".equals(type)) {
                MyClass2 myClass2 = new MyClass2();
                myClass2.id = id;
                myClass2.type = type;
                return myClass2;
            }
            return null; // or throw an exception
        }
    }
    
    public class SomeClass {
        @JsonDeserialize(contentUsing = CustomDeserializer.class)
        ArrayList<BaseClass> list;
    }
    
    Login or Signup to reply.
  2. You can make this happen simply using Jackson annotations:

    @JsonTypeInfo(use = NAME, property = "type")
    @JsonSubTypes(
      @Type(MyClass1.class, name = "MyClass1"),
      @Type(MyClass2.class, name = "MyClass2")
    )
    public class BaseClass {
      String id;
    }
    

    You may also want to look into other values for use, such as CLASS or MINIMAL_CLASS.

    Login or Signup to reply.
  3. See jackson polymorphic type handling annotations

    You should be able to do something like

    @JsonTypeInfo(
       use = JsonTypeInfo.Id.NAME, 
       include = As.PROPERTY, 
       property = "type"
    )
    @JsonSubTypes({
       @JsonSubTypes.Type(value = MyClass1.class, name = "MyClass1"),
       @JsonSubTypes.Type(value = MyClass2.class, name = "MyClass2")
    })
    public class BaseClass {
        String id;
        String type;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search