春季杰克逊ObjectMapper的生命周期

时间:2020-10-08 10:32:07

标签: java json spring spring-boot jackson

环境:

我使用的是Spring Boot 2.3.3.RELEASE版本


问题

我用@JsonComponent注解注册自定义反序列化器。

在某些模块和测试中,我@Autowire个杰克逊ObjectMapper

问题1:我无法在@JsonComponent中使用@Autowire ObjectMapper,否则@JsonComponent将被完全忽略(没有错误消息)

问题2:我想在@JsonComponent中拥有相同的ObjectMapper实例(或至少具有相同配置的OM),而我可以通过Autowire在其他组件中获得该实例


示例

由于我不希望对某些字段进行自定义反序列化,因此我使用ObjectMapper在自定义反序列化器中使用convertValue()

我注意到,我无法@Autowire在我的任何反序列化器中进行ObjectMapper操作,否则将无法为应用程序中自动连线的其他ObjectMappers选择配置(因此反序列化器未正确注册)

我正在使用(ObjectMapper) jsonParser.getCodec();

在反序列化器中获取ObjectMapper。

但是此ObjectMapper的配置不正确(例如,将忽略类/方法上的注释)。

我要反序列化对象,如下所示:

@Test
void testDeserializeFoo() throws IOException {
    ObjectMapper om = new ObjectMapper(); // this is obtained by jsonParser in deserializer but it behaves the same, since the ObjectMapper lacks the configuration
    InputStream is = getClass().getResourceAsStream("/json/foo.json");
    JsonNode fooNode = om.readTree(is);
    Foo foo =  om.convertValue(fooNode, Foo.class);
    log.info("Foo: " + foo);
}

Foo的构造函数带有@JsonCreator注释。

问题是,我从自定义反序列化器中的解析器获取的ObjectMapper忽略了此批注。这将导致以下错误消息:

类型的无效类型定义 Foo: 参数0没有属性名称,不可注入:不能用作 创作者[ , 注释:{interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode = DEFAULT)}]

是否可以在我的自定义反序列化器中具有与自动装配时在其他组件中使用的ObjectMapper相同的实例?


修改

可能的解决方案/测试:

我正在像这样测试我的解串器:

private JsonParser getJsonParser(String resource) throws IOException {
        InputStream src = getInputStream(resource);
        return objectMapper.createParser(src);
}
    
@Test
void testDeserializeFoo() throws IOException {
    JsonParser parser = getJsonParser("/json/foo.json");
    Foo foo = deserializer.deserialize(parser, null);
    System.out.println(foo);
}

问题在于getParser()方法中的objectMapper一直都是新实例。现在,我使用自动装配的objectMapper。但这有什么作用?


结论:

我想在我的JsonComponents(自定义反序列化器)中使用与Autowired ObjectMapper(其他组件中由spring提供)相同的ObjectMapper实例,或者至少使用具有相同配置的ObjectMapper。

使用配置,我的意思是:在类,方法,字段/已注册模块和JsonComponents上启用Jackson功能/注释配置

有人可以解释一下吗?

  • 如何以及何时在Spring中配置ObjectMapper(何时 注释配置(JsonCreator,JsonProperty),功能 自定义application.yml中的配置(例如接受大写) 在ObjectMapper上注册的JsonComponents等
  • 此objectMapper实例的生命周期是什么?
  • 什么是ContextConfiguration的生命周期, 反序列化配置?
  • Spring和Jackson的上下文如何相互关联?

我在寻找相关主题,其他答案与以下地方有关:

  • Spring和Jackson的上下文不同(但是为什么,这意味着什么?)
  • 您需要一个HandlerInstantiator来自动装配(我假设这是我的春季版本中的默认值,这也不能解释为什么在其中一个反序列化器中自动装配ObjectMapper时,我的自定义反序列化器在没有任何错误消息的情况下没有被拾取) >

1 个答案:

答案 0 :(得分:1)

通常,您可以使用Jackson2ObjectMapperBuilder和build()来生成应用了所有最近设置的新对象映射器实例。默认的ObjectMapper由JackonAutoConfiguration中的JackonsObjectMapperConfiguration提供。所有jackson2对象映射器生成器实例都是由JacksonAutoConfiguration中的JacksonObjectMapperBuilderConfiguration创建的。有关配置对象映射器的详细信息,请参见here

如果您不喜欢JacksonAutoConfiguration中的标准默认值,则可以使用Jackson2ObjectMapperBuilderCustomizerConfiguration进一步自定义jackson2对象映射器生成器

签出此answer-它会回答您的其他问题

即将发布-使用jackson2objectbuilder / build或为JsonComponent批注注释的ser / deser自动装配对象映射器时出现相同的问题。所有这些批注均由JacksonAutoConfiguration中定义的JsonComponentModule bean进行扫描,并已注册到默认对象映射器以及jackson2对象映射器构建器创建的所有实例。因此,不可能使用未构建的对象映射器并同时注册ser / deser。没错,Spring抑制了异常(beancurrentlyincreationexception),并且json组件模块未向对象映射器的消息unresolvale循环引用注册。

除了在spring托管之外创建新的对象映射器外,我没有找到其他解决方案。