Michael Minella Michael Minella - 1 year ago 176
JSON Question

Serialize/Deserialize Map<String, Object> with Jackson

I have a class that looks like the following

public class MyClass {
private String val1;
private String val2;
private Map<String,Object> context;
// Appropriate accessors removed for brevity.

I'm looking to be able to make the round trip with Jackson from object to JSON and back. I can serialize the object above fine and receive the following output:

"val1": "foo",
"val2": "bar",
"context": {
"key1": "enumValue1",
"key2": "stringValue1",
"key3": 3.0

The issue I'm running into is that since the values in the serialized map do not have any type information, they are not deserialized correctly. For example, in the sample above, enumValue1 should be deserialized as an enum value but is instead deserialized as a String. I've seen examples for basing what type on a variety of things, but in my scenario, I won't know what the types are (they will be user generated objects that I won't know in advance) so I need to be able to serialize the type information with the key value pair. How can I accomplish this with Jackson?

For the record, I'm using Jackson version 2.4.2. The code I'm using to test the round trip is as follows:

public void testJsonSerialization() throws Exception {
// Get test object to serialize
T serializationValue = getSerializationValue();
// Serialize test object
String json = mapper.writeValueAsString(serializationValue);
// Test that object was serialized as expected
// Deserialize to complete round trip
T roundTrip = (T) mapper.readValue(json, serializationValue.getClass());
// Validate that the deserialized object matches the original one

Since this is a Spring based project, the mapper is being created as follows:

public static class SerializationConfiguration {

public ObjectMapper mapper() {
Map<Class<?>, Class<?>> mixins = new HashMap<Class<?>, Class<?>>();
// Add unrelated MixIns

return new Jackson2ObjectMapperBuilder()
.dateFormat(new ISO8601DateFormatWithMilliSeconds())

Answer Source

I think the simplest way of achieve what you want is using:


This will add type information in the serialized json.

Here you are a running example, that you will need to adapt to Spring:

public class Main {

    public enum MyEnum {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        MyClass obj = new MyClass();
        obj.setContext(new HashMap<String, Object>());

        obj.getContext().put("key1", "stringValue1");
        obj.getContext().put("key2", MyEnum.enumValue1);
        obj.getContext().put("key3", 3.0);

        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);


        MyClass readValue = mapper.readValue(json, MyClass.class);
        //Check the enum value was correctly deserialized
        Assert.assertEquals(readValue.getContext().get("key2"), MyEnum.enumValue1);


The object will be serialized into something similar to:

[ "so_27871226.MyClass", {
  "val1" : "foo",
  "val2" : "var",
  "context" : [ "java.util.HashMap", {
    "key3" : 3.0,
    "key2" : [ "so_27871226.Main$MyEnum", "enumValue1" ],
    "key1" : "stringValue1"
  } ]
} ]

And will be deserialized back correctly, and the assertion will pass.

Bytheway there are more ways of doing this, please look at https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization for more info.

I hope it will help.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download