【发布时间】:2015-03-08 09:41:00
【问题描述】:
我有一个如下所示的类
public class MyClass {
private String val1;
private String val2;
private Map<String,Object> context;
// Appropriate accessors removed for brevity.
...
}
我希望能够与 Jackson 一起从 object 到 JSON 再返回。我可以很好地序列化上面的对象并接收以下输出:
{
"val1": "foo",
"val2": "bar",
"context": {
"key1": "enumValue1",
"key2": "stringValue1",
"key3": 3.0
}
}
我遇到的问题是,由于序列化映射中的值没有任何类型信息,因此它们没有正确反序列化。例如,在上面的示例中,应该将 enumValue1 反序列化为枚举值,但反序列化为字符串。我已经看到了基于各种事物的类型的示例,但在我的场景中,我不知道类型是什么(它们将是用户生成的对象,我不会提前知道)所以我需要能够用键值对序列化类型信息。我如何与 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();
}
}
【问题讨论】:
-
好吧,
Object当然不会有任何类型信息;除了 1. 为您的context实例变量创建一个 POJO(首选)之外,别无他法;或 2. 不要使用Map<String, Object>,而是使用ObjectNode。无论如何,这是代码异味的主要示例。 -
context变量的使用方式与HttpSession类似(准确地说,它代表 Spring Batch 的ExecutionContext),所以我不会认为它是一种气味……就是这样Map用于。我不明白的是为什么杰克逊不能添加指示类型的字段。如果它有值,它就有类,因此可以确定类型。我错过了什么? -
它会在哪里添加这个字段?您只需告诉它反序列化为
Object。至少,ObjectNode的优势在于您可以直接获取 JSON;因此,您可以使用JsonNode提供的所有帮助查询字段的类型。