Map a JSON field that can have different types with Jackson? Map a JSON field that can have different types with Jackson? json json

Map a JSON field that can have different types with Jackson?


The field cars can either contain a list of Car objects ... This works:

{    "id" : "1234",    "name" : "John Doe",    "cars" : {        "Tesla Model S" : {            "color" : "silver",            "buying_date" : "2012-06-01"        },        "Toyota Yaris" : {            "color" : "blue",            "buying_date" : "2005-01-01"        }    }}

The "cars" element value is not a list (aka array). It's a JSON object, which can also be considered a map-type collection, but it is not a list.

So, to rephrase the issue, the goal is to deserialize JSON that is sometimes an object and sometimes an empty string into a Java Map.

To solve this, I'm surprised ACCEPT_EMPTY_STRING_AS_NULL_OBJECT didn't work. I recommend logging an issue at http://jira.codehaus.org/browse/JACKSON.

You could implement custom deserialization. Following is an example solution. If the target data structure has other Map references, then this solution would need to be accordingly changed.

import java.io.File;import java.io.IOException;import java.util.HashMap;import java.util.Map;import org.codehaus.jackson.JsonNode;import org.codehaus.jackson.JsonParser;import org.codehaus.jackson.JsonProcessingException;import org.codehaus.jackson.ObjectCodec;import org.codehaus.jackson.Version;import org.codehaus.jackson.map.DeserializationContext;import org.codehaus.jackson.map.JsonDeserializer;import org.codehaus.jackson.map.ObjectMapper;import org.codehaus.jackson.map.module.SimpleModule;import org.codehaus.jackson.type.TypeReference;public class Foo{  public static void main(String[] args) throws Exception  {    SimpleModule module = new SimpleModule("CarsDeserializer", Version.unknownVersion());    module.addDeserializer(Map.class, new CarsDeserializer());    ObjectMapper mapper = new ObjectMapper().withModule(module);    Person person1 = mapper.readValue(new File("input1.json"), Person.class);    System.out.println(mapper.writeValueAsString(person1));    // {"id":1234,"name":"John Doe","cars":{"Tesla Model S":{"color":"silver","buying_date":"2012-06-01"},"Toyota Yaris":{"color":"blue","buying_date":"2005-01-01"}}}    Person person2 = mapper.readValue(new File("input2.json"), Person.class);    System.out.println(mapper.writeValueAsString(person2));    // {"id":1,"name":"The Dude","cars":{}}  }}class Person{  public int id;  public String name;  public Map<String, Car> cars;}class Car{  public String color;  public String buying_date;}class CarsDeserializer extends JsonDeserializer<Map<String, Car>>{  @Override  public Map<String, Car> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,      JsonProcessingException  {    ObjectCodec codec = jp.getCodec();    JsonNode node = codec.readTree(jp);    if (!"".equals(node.getTextValue()))    {      ObjectMapper mapper = new ObjectMapper();      return mapper.readValue(node, new TypeReference<Map<String, Car>>() {});    }    return new HashMap<String, Car>(); // or return null, if preferred  }}