java - jackson :反序列化为每个值都具有正确类型的 Map<String, Object>

标签 java json spring jackson

我有一个如下所示的类

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();
    }
}

最佳答案

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

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<String, Object>());

        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了解更多信息。

我希望它会有所帮助。

关于java - jackson :反序列化为每个值都具有正确类型的 Map<String, Object>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27871226/

相关文章:

python - 如何将多个 python 对象转储到 json 文件以及从 json 文件加载多个 python 对象?

java - 在 Spring 中,如何在任何 Java 应用程序中使用从 XML 文件创建 bean 的方法

spring - Tomcat 无法在 war 文件中找到 jsp

java - 其他 NaN 值是什么?

java - 新对象 : new operator vs serialization

java - 如何加载一个文件以供多种方法访问?

javascript - 以字符串形式检索整个 json 数组

javascript - 修改 JSON 对象时出现 TypeError _______________ 不是函数

java - 使用 spring security 登录操作之前的自定义验证?

java - 如何使用确认密码验证密码然后重定向?