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