Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson - How to process (deserialize) nested JSON?

{   vendors: [     {       vendor: {         id: 367,         name: "Kuhn-Pollich",         company_id: 1,       }     },     {       vendor: {         id: 374,         name: "Sawayn-Hermann",         company_id: 1,       }   }] } 

I have a Vendor object that can properly be deserialized from a single "vendor" json, but I want to deserialize this into a Vendor[], I just can't figure out how to make Jackson cooperate. Any tips?

like image 991
Sam Stern Avatar asked Jul 31 '12 19:07

Sam Stern


People also ask

How does Jackson read nested JSON?

A JsonNode is Jackson's tree model for JSON and it can read JSON into a JsonNode instance and write a JsonNode out to JSON. To read JSON into a JsonNode with Jackson by creating ObjectMapper instance and call the readValue() method. We can access a field, array or nested object using the get() method of JsonNode class.

How do I map nested values with Jackson?

Mapping With Annotations To map the nested brandName property, we first need to unpack the nested brand object to a Map and extract the name property. To map ownerName, we unpack the nested owner object to a Map and extract its name property.

How does Jackson deserialize dates from JSON?

How to deserialize Date from JSON using Jackson. In order to correct deserialize a Date field, you need to do two things: 1) Create a custom deserializer by extending StdDeserializer<T> class and override its deserialize(JsonParser jsonparser, DeserializationContext context) method.


1 Answers

Here is a rough but more declarative solution. I haven't been able to get it down to a single annotation, but this seems to work well. Also not sure about performance on large data sets.

Given this JSON:

{     "list": [         {             "wrapper": {                 "name": "Jack"             }         },         {             "wrapper": {                 "name": "Jane"             }         }     ] } 

And these model objects:

public class RootObject {     @JsonProperty("list")     @JsonDeserialize(contentUsing = SkipWrapperObjectDeserializer.class)     @SkipWrapperObject("wrapper")     public InnerObject[] innerObjects; } 

and

public class InnerObject {     @JsonProperty("name")     public String name; } 

Where the Jackson voodoo is implemented like:

@Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface SkipWrapperObject {     String value(); } 

and

public class SkipWrapperObjectDeserializer extends JsonDeserializer<Object> implements         ContextualDeserializer {     private Class<?> wrappedType;     private String wrapperKey;      public JsonDeserializer<?> createContextual(DeserializationContext ctxt,             BeanProperty property) throws JsonMappingException {         SkipWrapperObject skipWrapperObject = property                 .getAnnotation(SkipWrapperObject.class);         wrapperKey = skipWrapperObject.value();         JavaType collectionType = property.getType();         JavaType collectedType = collectionType.containedType(0);         wrappedType = collectedType.getRawClass();         return this;     }      @Override     public Object deserialize(JsonParser parser, DeserializationContext ctxt)             throws IOException, JsonProcessingException {         ObjectMapper mapper = new ObjectMapper();         ObjectNode objectNode = mapper.readTree(parser);         JsonNode wrapped = objectNode.get(wrapperKey);         Object mapped = mapIntoObject(wrapped);         return mapped;     }      private Object mapIntoObject(JsonNode node) throws IOException,             JsonProcessingException {         JsonParser parser = node.traverse();         ObjectMapper mapper = new ObjectMapper();         return mapper.readValue(parser, wrappedType);     } } 

Hope this is useful to someone!

like image 94
Patrick Avatar answered Sep 28 '22 04:09

Patrick