4
votes

I am trying to deserialize a rather complex POJOs JSON, where I would need to define a specific property-name to type resolution, but yet faild fininding this rather simple feature.

assume a class like:

class Example {
  int id;
  Map<String,Object> extras;
}

and Jackson is serializing the POJO correctly to JSON where the map is serialized to a key-value map just like expected:

{...
id:5,
extras:{object1:{...}, object2:{...}}
...}

now I would like to tell Jackson to explicitly deserialize the extras objects by their actual type. So I need to tell Jackson somehow to map "object1" to Type A and "object2" to type B.

Is this possible? Thanks.

4
Yes, it's possible. But you'll probably need to send in json type info for each object in map. - pawelzieba
I am not in control of the received json, even though I know the objects type. - joecks
How you're discerning object type? - pawelzieba
by name, I know that the key "object1" is belonging to the type A. - joecks

4 Answers

7
votes

There is nice guide how to deal with it: http://www.cowtowncoder.com/blog/archives/2010/03/entry_372.html

And another tutorial:
http://programmerbruce.blogspot.de/2011/05/deserialize-json-with-jackson-into.html

The 6th example from the second tutorial could be modified and deserializer would have loop with something similar to:

Map<String, Class> types = ...// map of supported types
JsonToken token = jsonParser.nextToken();
if(token == JsonToken.FIELD_NAME){ // "object1" etc.
    String name = jsonParser.getCurrentName();
    Class type = types.get(name);
    Object object = jsonParser.readValueAs(type);
}
1
votes

The easiest way is to enable so-called "default typing" -- it does roughly equivalent of adding @JsonTypeInfo annotation (which enables support polymorphic type handling) -- and this adds type information in values. So:

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
0
votes

If the Extras map contains only those 2 objects (object1 and object2) you can do the following

class TypeA {
    // TypeA body
}

class TypeB {
    // TypeB body
}

class Extras {
    private TypeA object1;
    private TypeB object2;
    // Getters and setters
}

class Example {
    int id;
    Extras extras;
}
0
votes

This is possible using a custom deserializer; see this link, for examples. In a nut shell, you need to tell Jackson what type a field should be unmarshalled to; although, this might be error prone if your serialized data (JSON) is dynamically changing.

You can then easily annotate your field's setter like so:

ObjectA value;

@JsonDeserialize(using=ObjectADeserializer.class)
public void setValue(ObjectA objectAValue) {
   this.value = objectAValue;
}