使用Jackson序列化/反序列化Map

我有一个类似于以下的类

public class MyClass { private String val1; private String val2; private Map context; // Appropriate accessors removed for brevity. ... } 

我希望能够与jackson一起往返于JSON并返回。 我可以将对象序列化为精细并接收以下输出:

 { "val1": "foo", "val2": "bar", "context": { "key1": "enumValue1", "key2": "stringValue1", "key3": 3.0 } } 

我遇到的问题是,由于序列化映射中的值没有任何类型信息,因此它们不会正确反序列化。 例如,在上面的示例中,enumValue1应该反序列化为枚举值,而是反序列化为String。 我已经看到了基于各种类型的类型的示例,但在我的场景中,我不知道类型是什么(它们将是用户生成的对象,我不会事先知道)所以我需要成为能够使用键值对序列化类型信息。 我怎样才能与jackson达成这个目标?

为了记录,我使用Jackson版本2.4.2。 我用来测试往返的代码如下:

 @Test @SuppressWarnings("unchecked") public void testJsonSerialization() throws Exception { // Get test object to serialize T serializationValue = getSerializationValue(); // Serialize test object String json = mapper.writeValueAsString(serializationValue); // Test that object was serialized as expected assertJson(json); // Deserialize to complete round trip T roundTrip = (T) mapper.readValue(json, serializationValue.getClass()); // Validate that the deserialized object matches the original one assertObject(roundTrip); } 

由于这是一个基于Spring的项目,因此映射器的创建方式如下:

 @Configuration public static class SerializationConfiguration { @Bean public ObjectMapper mapper() { Map<Class, Class> mixins = new HashMap<Class, Class>(); // Add unrelated MixIns .. return new Jackson2ObjectMapperBuilder() .featuresToDisable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS) .dateFormat(new ISO8601DateFormatWithMilliSeconds()) .mixIns(mixins) .build(); } } 

我认为实现你想要的最简单的方法是使用:

 ObjectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

这将在序列化的json中添加类型信息。

在这里你是一个运行的例子,你将需要适应Spring:

 public class Main { public enum MyEnum { enumValue1 } public static void main(String[] args) throws IOException { ObjectMapper mapper = new ObjectMapper(); MyClass obj = new MyClass(); obj.setContext(new HashMap()); obj.setVal1("foo"); obj.setVal2("var"); obj.getContext().put("key1", "stringValue1"); obj.getContext().put("key2", MyEnum.enumValue1); obj.getContext().put("key3", 3.0); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj); System.out.println(json); MyClass readValue = mapper.readValue(json, MyClass.class); //Check the enum value was correctly deserialized Assert.assertEquals(readValue.getContext().get("key2"), MyEnum.enumValue1); } } 

该对象将被序列化为类似于:

 [ "so_27871226.MyClass", { "val1" : "foo", "val2" : "var", "context" : [ "java.util.HashMap", { "key3" : 3.0, "key2" : [ "so_27871226.Main$MyEnum", "enumValue1" ], "key1" : "stringValue1" } ] } ] 

并且将被正确地反序列化,并且断言将通过。

顺便提一下,有更多的方法,请查看https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization了解更多信息。

我希望它会有所帮助。