简体   繁体   English

Spring中Jackson ObjectMapper的生命周期

[英]Lifecycle of Jackson ObjectMapper in Spring

Environment:环境:

I use spring boot version 2.3.3.RELEASE我使用 spring 引导版本 2.3.3.RELEASE


Problem问题

I register custom deserializers with @JsonComponent annotation.我使用@JsonComponent注释注册自定义反序列化器。

In some modules and tests I @Autowire jacksons ObjectMapper .在某些模块和测试中,我@Autowire jacksons ObjectMapper

Problem 1: I cannot @Autowire ObjectMapper in @JsonComponent or the @JsonComponent will be ignored completely (without error message)问题 1:我不能在 @JsonComponent 中使用 @Autowire ObjectMapper,否则 @JsonComponent 将被完全忽略(没有错误消息)

Problem 2: I want to have the same instance of ObjectMapper in @JsonComponent (or at least OM with same configuration) that I can obtain by Autowire in other Components问题 2:我想在 @JsonComponent 中拥有相同的 ObjectMapper 实例(或至少具有相同配置的 OM),我可以通过 Autowire 在其他组件中获得


Example例子

Since I don't want custom deserialization for some fields I use the ObjectMapper to use convertValue() in my custom deserializers.由于我不想对某些字段进行自定义反序列化,因此我使用 ObjectMapper 在我的自定义反序列化器中使用convertValue()

I noticed, that I cannot @Autowire the ObjectMapper in any of my Deserializers or the Configuration will not be picked up for other ObjectMappers that are autowired in my Application (So the Deserializers are not registered correctly)我注意到,我不能在我的任何反序列化器中@Autowire ObjectMapper,否则在我的应用程序中自动装配的其他 ObjectMappers 将不会获取配置(因此反序列化器未正确注册)

I'm obtaining the ObjectMapper in the Deserializer with (ObjectMapper) jsonParser.getCodec();我正在使用(ObjectMapper) jsonParser.getCodec();

But this ObjectMapper is not configured correctly (meaning eg annotations on class/methods are ignored).但是这个 ObjectMapper 配置不正确(意味着例如类/方法上的注释被忽略)。

I want to deserialize my object as follows:我想反序列化我的 object 如下:

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

The constructor of Foo is annotated with @JsonCreator . Foo 的构造函数用@JsonCreator注释。

The Problem is, that this annotation is ignored by the ObjectMapper I get from the parser in the custom Deserializer.问题是,这个注释被我从自定义反序列化器中的解析器获得的 ObjectMapper 忽略了。 This results in the following error message:这会导致以下错误消息:

Invalid type definition for type Foo : Argument #0 has no property name, is not Injectable: can not use as Creator [constructor for Foo, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] Foo类型的类型定义无效:参数 #0 没有属性名称,不可注入:不能用作 Creator [Foo 的构造函数,注释:{interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson。 annotation.JsonCreator(mode=DEFAULT)}]

Is it possible to have the same instance of ObjectMapper in my custom Deserializer that is used in other Components when Autowired?是否可以在我的自定义解串器中使用与自动装配时在其他组件中使用的相同的 ObjectMapper 实例?


Edit编辑

Possible Solution / Test:可能的解决方案/测试:

I was testing my deserializer like this:我正在像这样测试我的解串器:

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

The problem was that the objectMapper in getParser() method was a new instance all the time.问题是 getParser() 方法中的 objectMapper 始终是一个新实例。 Now I use the autowired objectMapper.现在我使用自动装配的 objectMapper。 But how does this have any effect?但这有什么作用呢?


Conclusion:结论:

I want to use the same instance of ObjectMapper in my JsonComponents (custom deserializers) as the Autowired ObjectMapper (which is provided by spring in other Components), or at least an ObjectMapper with the same configuration.我想在我的 JsonComponents(自定义反序列化器)中使用与 Autowired ObjectMapper(由其他组件中的 spring 提供)相同的 ObjectMapper 实例,或者至少使用具有相同配置的 ObjectMapper。

With configuration I mean: Enabled Jackson Features / Annotation Configurations on classes, methods, fields / registered modules and JsonComponents配置我的意思是:启用 Jackson 类、方法、字段/注册模块和 JsonComponents 的功能/注释配置

Can someone please explain:有人可以解释一下吗:

  • how and when ObjectMapper is configured in Spring (when are Annotation configurations (JsonCreator, JsonProperty), Feature configurations (like accepting upper case) in application.yml, Custom JsonComponents etc registered on an ObjectMapper如何以及何时在 Spring 中配置 ObjectMapper(何时在 application.yml 中注册注释配置(JsonCreator、JsonProperty)、特征配置(如接受大写)、自定义 JsonComponents 等在 ObjectMapper 上注册
  • what is the lifecycle of this objectMapper instance?这个 objectMapper 实例的生命周期是什么?
  • What is the lifecycle of a ContextConfiguration, DeserializationConfiguration? ContextConfiguration、DeserializationConfiguration 的生命周期是什么?
  • How does Spring and Jackson context relate to each other? Spring 和 Jackson 上下文如何相互关联?

I looked for related topics, other answers related where:我寻找相关主题,其他相关答案在哪里:

  • Spring and Jackson context are not the same (but why, what does this mean?) Spring 和 Jackson 上下文不一样(但是为什么,这是什么意思?)
  • You need a HandlerInstantiator to Autowire (this is already default in my spring version I assume, also this does not explain why my custom deserializers are not picked up without any error messages when autowiring ObjectMapper in one of the deserializers)您需要一个 HandlerInstantiator 来自动装配(这在我假设的 spring 版本中已经是默认设置,这也不能解释为什么在其中一个反序列化器中自动装配 ObjectMapper 时没有任何错误消息地选择我的自定义反序列化器)

In general you can use Jackson2ObjectMapperBuilder and build() to generate new object mapper instance with all the recent settings applied.通常,您可以使用 Jackson2ObjectMapperBuilder 和 build() 生成新的 object 映射器实例,并应用所有最近的设置。 The default ObjectMapper is provided by JackonsObjectMapperConfiguration in JackonAutoConfiguration.默认的 ObjectMapper 由 JackonAutoConfiguration 中的 JackonsObjectMapperConfiguration 提供。 All jackson2 object mapper builder instances are created by JacksonObjectMapperBuilderConfiguration in JacksonAutoConfiguration.所有 jackson2 object 映射器构建器实例均由 JacksonAutoConfiguration 中的 JacksonObjectMapperBuilderConfiguration 创建。 Details on configuring object mapper can be found here可以在此处找到有关配置 object 映射器的详细信息

You can further customize jackson2 object mapper builder using Jackson2ObjectMapperBuilderCustomizerConfiguration if you don't like the standard defaults in JacksonAutoConfiguration如果您不喜欢 JacksonAutoConfiguration 中的标准默认值,则可以使用 Jackson2ObjectMapperBuilderCustomizerConfiguration 进一步自定义 jackson2 object 映射器构建器

Checkout this answer - it will answer your other questions检查这个答案- 它会回答你的其他问题

Coming to issue - Had the same issue when using jackson2objectbuilder/build or autowiring object mapper for ser/deser annotated with JsonComponent annotation.即将发布 - 使用 jackson2objectbuilder/build 或自动装配 object 映射器时遇到同样的问题,用于带有 JsonComponent 注释的 ser/deser 注释。 All these annotations are scanned by JsonComponentModule bean defined in JacksonAutoConfiguration and are registered with default object mapper and all the instances created by jackson2 object mapper builder.所有这些注释都由 JacksonAutoConfiguration 中定义的 JsonComponentModule bean 扫描,并使用默认的 object 映射器和 jackson2 object 映射器构建器创建的所有实例进行注册。 So it is not possible to use the not built object mapper and register the ser/deser at the same time.所以不可能使用未构建的 object 映射器并同时注册 ser/deser。 You are right the exception ( beancurrentlyincreationexception ) is suppressed by spring and json component module is not registered with message unresolvale circular reference for object mapper.您是对的,异常 (beancurrentlyincreationexception) 被 spring 抑制,并且 json 组件模块未注册 object 映射器的消息未解析循环引用。

I didn't find any solution other than creating a new object mapper outside of spring managed.除了在 spring 托管之外创建一个新的 object 映射器之外,我没有找到任何解决方案。

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

相关问题 如何在 Spring 引导中为 Camel 配置 Jackson ObjectMapper - How to configure Jackson ObjectMapper for Camel in Spring Boot 使用 Jackson Objectmapper 配置的 Spring boot in Hibernate - Use Jackson Objectmapper configured by Spring boot in Hibernate Spring和Jackson ObjectMapper不使用自定义Filter - Spring and Jackson ObjectMapper not working with custom Filter 将 spring-data-elasticsearch 注释与 Jackson ObjectMapper 一起使用? - Use spring-data-elasticsearch annotations with Jackson ObjectMapper? 如何获取Spring 4.1使用的Jackson ObjectMapper? - How do I obtain the Jackson ObjectMapper in use by Spring 4.1? 避免将 Jackson xmlMapper 用作 Spring 的默认 objectMapper - Avoid Jackson xmlMapper being used as default objectMapper with Spring 有可能在spring-data-mongodb中注入一个自定义的Jackson ObjectMapper吗? - Is is possible to inject a custom Jackson ObjectMapper in spring-data-mongodb? 是否可以在不诉诸XML的情况下为Spring创建自定义Jackson objectMapper? - Is it possible to create a custom Jackson objectMapper for Spring without resorting to XML? 如何使用 Spring application.properties 自定义 Jackson ObjectMapper? - How to customize Jackson ObjectMapper with Spring application.properties? 如何使用Jackson的ObjectMapper和Spring的RestTemplate处理各种响应? - How to handle various responses with Jackson ObjectMapper and Spring's RestTemplate?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM