繁体   English   中英

配置 Jackson ObjectMapper 的意外序列化行为

[英]Unexpected serialization behavior with configured Jackson ObjectMapper

我正在使用 Jackson 2.10.5 将同一个java.util.Date对象序列化三次。

  1. 第一次,使用基本的 Jackson ObjectMapper 我看到了时间戳。
  2. 然后我配置相同的ObjectMapper ,并重写。 我得到相同的结果。
  3. 然后我构造一个新的ObjectMapper ,以同样的方式配置它。 我得到了一个不同的结果,类名和 JSON 列表中的时间戳。

该配置旨在告诉ObjectMapperjava.util.Date之外的每个对象的类名作为 JSON 属性包含在内。

所以我有两个问题。 第一个是为什么在第三种情况下日期对象序列化不同? 任何关于以不同方式使用PolymorphicTypeMapper建议将不胜感激。

第二个是为什么第一个和第二个是相同的(是因为对象映射器有一个缓存(哎哟!)?)。

[编辑:我应该提到这个用例是作为 Jersey 的 JSON 提供程序。 我有一种在启动时生成和配置ObjectMapper的方法,但是配置 per-write 的(不)能力仅适用于上面的测试代码。]

private PolymorphicTypeValidator getPTV() {
    return BasicPolymorphicTypeValidator.builder()
            .denyForExactBaseType(Date.class)
            .build();
}


@Test
public void serializationTest() {
    try {
        Date now = new Date();

        // Create an object mapper and serialize the date
        ObjectMapper om = new ObjectMapper();
        String serialized1 = om.writeValueAsString(now); // result: 1605744866827

        om.activateDefaultTypingAsProperty(getPTV(), ObjectMapper.DefaultTyping.EVERYTHING, "@class");
        String serialized2 = om.writeValueAsString(now); // result: 1605744866827

        ObjectMapper om2 = new ObjectMapper();
        om2.activateDefaultTypingAsProperty(getPTV(), ObjectMapper.DefaultTyping.EVERYTHING, "@class");
        String serialized3 = om2.writeValueAsString(now); // result: ["java.util.Date",1605744866827]

        Logger.getLogger(SerializationTest.class).info(serialized1);
        Logger.getLogger(SerializationTest.class).info(serialized2);
        Logger.getLogger(SerializationTest.class).info(serialized3);

        Assert.assertEquals("Unexpected change in serialization 1-2", serialized1, serialized2);
        Assert.assertEquals("Unexpected change in serialization 1-3", serialized1, serialized3);

    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
}

这是输出:

INFO  2020-11-18 16:14:27,065 [main] <> test.SerializationTest : 1605744866827
INFO  2020-11-18 16:14:27,066 [main] <> test.SerializationTest : 1605744866827
INFO  2020-11-18 16:14:27,066 [main] <> test.SerializationTest : ["java.util.Date",1605744866827]

org.junit.ComparisonFailure: Unexpected change in serialization 1-3 
Expected :1605744866827
Actual   :["java.util.Date",1605744866827]

阅读文档,即ObjectMapper的 javadoc,它说(我用粗体突出显示)

Mapper 实例是完全线程安全的,前提是实例的所有配置发生在任何读取或写入调用之前 如果映射器的配置在第一次使用后被修改,更改可能生效也可能不生效,并且配置调用本身可能会失败 如果您需要使用不同的配置,您有两种主要的可能性:

  • 构造并使用ObjectReader进行读取,使用ObjectWriter进行写入。 这两种类型都是完全不可变的,您可以使用ObjectMapper工厂方法或读取器/ ObjectMapper器本身自由地创建具有不同配置的新实例。 构建新的ObjectReaderObjectWriter是一个非常轻量级的操作,因此通常适合根据需要在每次调用的基础上创建它们,以配置 JSON 的可选缩进等内容。

  • 如果通过ObjectReaderObjectWriter无法获得特定类型的可配置ObjectWriter ,您可能需要使用多个ObjectMapper来代替(例如:您不能即时更改混合注释;或者,一组自定义(反)序列化程序) . 为了帮助使用这种用法,您可能需要使用方法copy()创建具有特定配置的映射器的克隆,并允许在使用之前配置复制的实例。 请注意, copy()操作与构造一个新的ObjectMapper实例一样昂贵:如果可能,如果您打算将它们用于多个操作,您仍然应该池化和重用映射器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM