Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson Unmarshall custom object instead of LinkedHashMap

Tags:

java

json

jackson

I have a Java object Results:

public class MetaData {
    private List<AttributeValue<String,Object>> properties
    private String name
    ...

    ... getters/setters ...
}

The AttributeValue class is a generic key-value class. It's possible different AttributeValue's are nested. The (value) Object will then be another AttributeValue and so forth.

Due to legacy reasons the structure of this object cannot be altered.

I have my JSON, which I try to map to this object. All goes well for the regular properties. Also the first level of the list is filled with AttributeValues.

The problem is the Object. Jackson doesn't know how to interpret this nested behavior and just makes it a LinkedHashMap.

I'm looking for a way to implement custom behavior to tell Jackson this has to be a AttributeValue-object instead of the LinkedHashMap.

This is how I'm currently converting the JSON:

ObjectMapper om = new ObjectMapper();
MetaData metaData = om.readValue(jsonString, new TypeReference<MetaData>(){});

And this is example JSON. (this is obtained by serializing an existing MetaData object to JSON, I have complete control over this syntax).

{
    "properties":[
        {
            "attribute":"creators",
            "value":[
                {
                    "attribute":"creator",
                    "value":"user1"
                },{
                    "attribute":"creator",
                    "value":"user2"
                }
            ]
        },{
            "attribute":"type",
            "value": "question"
        }
    ],
    "name":"example"
}

(btw: I've tried the same using GSON, but then the object is a StringMap and the problem is the same. Solutions using GSON are also welcome).

edit In Using Jackson ObjectMapper with Generics to POJO instead of LinkedHashMap there is a comment from StaxMan: "LinkedHashMap is only returned when type information is missing (or if Object.class is defined as type)."

The latter seems to be the issue here. Is there a way I can override this?

like image 388
user3319803 Avatar asked Jul 28 '15 07:07

user3319803


People also ask

How does Jackson convert object to JSON?

Converting Java object to JSON In it, create an object of the POJO class, set required values to it using the setter methods. Instantiate the ObjectMapper class. Invoke the writeValueAsString() method by passing the above created POJO object. Retrieve and print the obtained JSON.

Can ObjectMapper be reused?

Creating an ObjectMapper is quite expensive. Therefore it is recommended that you reuse your ObjectMapper instance. The Jackon ObjectMapper is thread-safe so it can safely be reused.

How does Jackson ObjectMapper work?

The Jackson ObjectMapper can parse JSON from a string, stream or file, and create a Java object or object graph representing the parsed JSON. Parsing JSON into Java objects is also referred to as to deserialize Java objects from JSON. The Jackson ObjectMapper can also create JSON from Java objects.

Does Jackson ObjectMapper use reflection?

Jackson is a framework that provides the means to read and write objects to and from JSON. Typically, it tries to use built in support for common classes and simple types. It will also use a default serializer based on reflection to write the JSON, but will need some guidance for more complex custom objects.


1 Answers

If you have control over the serialization, try calling enableDefaultTyping() on your mapper.

Consider this example:

Pair<Integer, Pair<Integer, Integer>> pair = new Pair<>(1, new Pair<>(1, 1));
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(pair);
Pair result = mapper.readValue(str, Pair.class);

Without enableDefaultTyping(), I would have str = {"k":1,"v":{"k":1,"v":1}} which would deserialize to a Pair with LinkedHashMap.

But if I enableDefaultTyping() on mapper, then str = {"k":1,"v":["Pair",{"k":1,"v":1}]} which then perfectly deserializes to Pair<Integer, Pair<...>>.

like image 129
hotkey Avatar answered Oct 20 '22 00:10

hotkey