3

I'm attempting to use Jackson to serialize and deserialize a map containing arbitrary objects. According to the docs I've read I should be able to use enableDefaultTyping() to tell Jackson to store the info I need in serialization, and have written the following simple test:

  @Test
  public void testObjectMap()
  {
    final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();

    final Map<String, Object> map = Maps.newHashMap();
    map.put("test1", new Date());
    map.put("test2", new InetSocketAddress(10));

    try
    {
      final String ser = mapper.writeValueAsString(map);
      System.err.println(ser);
      final Map<String, Object> deser = this.mapper.readValue(ser, new TypeReference<Map<String, Object>>(){});
      assertTrue(deser.get("test1") instanceof Date);
      assertTrue(deser.get("test2") instanceof InetSocketAddress);
    }
    catch (final IOException e)
    {
      fail("Failed", e);
    }
  }

The serialization looks okay, in that the System.err.println(ser) line in the above code produces the output:

{"test1":["java.util.Date",1408312196267],"test2":["java.net.InetSocketAddress","0.0.0.0:10"]}

But the deserialization attempt fails with the following error:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.util.Map
 at [Source: {"test1":["java.util.Date",1408312196267],"test2":["java.net.InetSocketAddress","0.0.0.0:10"]}; line: 1, column: 1]
 at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
 at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:841)
 at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:122)
 at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:93)
 at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromObject(AsArrayTypeDeserializer.java:58)
 at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserializeWithType(MapDeserializer.java:342)
 at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:41)
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051)
 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2153)
 at test.JacksonModuleTest.testObjectMap(JacksonModuleTest.java:119)

I'm unsure what Jackson is complaining about here; I can only assume that it expects the map itself to have some sort of typing but I'm unsure how to provide this.

I'm using jackson 2.4.0

1 Answers1

3

You should take a look at How to convert a JSON string to a Map<String, String> with Jackson JSON where there is the following code :

JsonFactory factory = new JsonFactory(); 
ObjectMapper mapper = new ObjectMapper(factory); 
TypeReference<HashMap<String,Object>> typeRef 
        = new TypeReference<HashMap<String,Object>>() {};

HashMap<String,Object> o = mapper.readValue(inputFile, typeRef); 

Maybe the fact that you used the abstract class Map instead of a concrete implementation (HashMap in the above code) explains that Jackson has some difficulties when trying to fill this structure...

Community
  • 1
  • 1
Orabîg
  • 11,251
  • 6
  • 31
  • 53
  • 1
    Thanks for the answer. Although the code didn't make any difference, the fact that I was attempting to use an abstract type in the `TypeReference` was the issue and changing `Map` to `HashMap` in my `readValue()` fixed this issue. An alternative was to change my `writeValueAsString()` line to use `mapper.WriterWithType(HashMap.class).writeValueAsString()`, which I might prefer as it allows me to define the concrete class when writing the JSON rather than when reading it. –  Aug 17 '14 at 22:34