Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json deserialization into other class hierarchy using Jackson

Tags:

Now i'm working with Jackson and i have some questions about it.

First of all. I have two services, first is data collecting and sending service and second receive this data and, for example, log it into a file.

So, first service has class hierarchy like this:

         +----ConcreteC          | Base ----+----ConcreteA          |          +----ConcreteB 

And second service has class hierarchy like this:

ConcreteAAdapter extends ConcreteA implements Adapter {} ConcreteBAdapter extends ConcreteB implements Adapter {} ConcreteCAdapter extends ConcreteC implements Adapter {} 

The first service knows nothing about ConcreteXAdapter.

The way i'm sending the data on the first service:

Collection<Base> data = new LinkedBlockingQueue<Base>() JacksonUtils utils = new JacksonUtils(); data.add(new ConcreteA()); data.add(new ConcreteB()); data.add(new ConcreteC()); ... send(utils.marshall(data)); ...  public class JacksonUtils {      public byte[] marshall(Collection<Base> data) throws IOException {         ByteArrayOutputStream out = new ByteArrayOutputStream() {             @Override             public byte[] toByteArray() {                 return buf;             }         };          getObjectMapper().writeValue(out, data);         return out.toByteArray();     }     protected ObjectMapper getObjectMapper() {         return new ObjectMapper();     }      public Object unmarshall(byte[] json) throws IOException {         return getObjectMapper().readValue(json, Object.class);     }      public <T> T unmarshall(InputStream source, TypeReference<T> typeReference) throws IOException {         return getObjectMapper().readValue(source, typeReference);     }      public <T> T unmarshall(byte[] json, TypeReference<T> typeReference) throws IOException {         return getObjectMapper().readValue(json, typeReference);     } } 

So, i want to desirialize json into Collection of ConcreteXAdapter, not into Collection of ConcreteX (ConcreteA -> ConcreteAAdapter, ConcreteB -> ConcreteBAdapter, ConcreteC -> ConcreteCAdapter). In the case i described i want to get:

Collection [ConcreteAAdapter, ConcreteBAdapter, ConcreteCAdapter] 

How can i do this?

like image 274
pbespechnyi Avatar asked Apr 26 '12 08:04

pbespechnyi


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 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.

How does Jackson parse JSON?

databind. ObjectMapper ) is the simplest way to parse JSON with Jackson. 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.


1 Answers

For this purpose you need to pass additional info in JSON:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME,        include=JsonTypeInfo.As.PROPERTY, property="@type") class Base { ... } 

Then on serialization it will add @type field:

objectMapper.registerSubtypes(             new NamedType(ConcreteAAdapter.class, "ConcreteA"),             new NamedType(ConcreteBAdapter.class, "ConcreteB"),             new NamedType(ConcreteCAdapter.class, "ConcreteC")             );  // note, that for lists you need to pass TypeReference explicitly objectMapper.writerWithType(new TypeReference<List<Base>>() {})      .writeValueAsString(someList);       {       "@type" : "ConcreteA",       ...     } 

on deserialization it will be:

    objectMapper.registerSubtypes(             new NamedType(ConcreteA.class, "ConcreteA"),             new NamedType(ConcreteB.class, "ConcreteB"),             new NamedType(ConcreteC.class, "ConcreteC")             );     objectMapper.readValue(....) 

More info here

like image 126
Eugene Retunsky Avatar answered Sep 19 '22 16:09

Eugene Retunsky