ObjectMapper 的两个实例

Posted

技术标签:

【中文标题】ObjectMapper 的两个实例【英文标题】:Two instances of ObjectMapper 【发布时间】:2020-02-13 12:55:33 【问题描述】:

有没有办法为不同的目的创建两个 ObjectMapper 实例。

修改后的 ObjectMapper

    @Component
    class MyObjectMapper extends ObjectMapper
      public MyObjectMapper()
        super();
      

    public MyObjectMapper(MyObjectMapper om) 
        super(om);
     

    @Override
    public MyObjectMapper copy() 
        return new MyObjectMapper(this);
     
   

现在按如下方式使用

@Autowired ObjectMapper objectMapper; //performs standard serialization
@Autowire MyObjectMapper myMapper; //i can add custom filters in thiis mapper.

我尝试了类似的设置,但自定义映射器实际上会影响原始映射器所有 rest controllers 抛出 JSON parse error: Unrecognized field

编辑:不确定这一点是否非常重要,但仍在添加 我正在使用spring-boot-starter-json

【问题讨论】:

自定义映射器实际上会影响原始映射器”您实际上定义了两个 ObjectMapper 组件,还是 sn-p 的映射器是您拥有的唯一组件? Mapper 是我唯一拥有的组件。原因是,将过滤器添加到 Autowired ObjectMapper 会永久应用更改。但我只需要在某些地方进行特殊的序列化。我可以在需要时做一个“新”,但我正在寻找一些干净的东西 我不明白你在说什么。据我所知,如果这是您与ObjectMapper 相关的唯一配置,那么@Autowired ObjectMapper@Autowired MyObjectMapper 是完全相同的bean。您需要声明两个组件 bean:一个用于“干净”映射器,另一个 bean 用于自定义映射器。由于他们都是自动接线候选人,因此您需要对两者都进行资格认证并声明您要尝试自动接线(或对其中一个进行初步处理)。就像您在回答中所做的那样。 @Prokhorov 首先,MyObjectMapper 和 ObjectMapper 不是完全相同的 bean。使它相同的是你正在调用的'new ObjectMapper()',这是因为,我使用了一个自动的'Spring Boot Starter Json'。如果你使用标准的杰克逊和'@Bean',这可能会变得不那么模棱两可自己。 【参考方案1】:

好的。结合Aniket 的回答,找出了问题所在,仍在寻找更多解释。

而不是将 ObjectMapper 实例化为 new ObjectMapper()。使用Mapper 构建它已修复它。

所以,两个有多个 ObjectMapper 实例

@Primary
@Bean
public ObjectMapper objectMapper()
   return new Jackson2ObjectMapperBuilder()
                .build();


@Bean("customMapper")
public ObjectMapper customMapper()
  ObjectMapper customMapper = new Jackson2ObjectMapperBuilder().build();
     mapper.<your customization , filters, providers etc;>
     return mapper;

@Primary 将在所有默认情况下使用,即当您只是 @Autowire 或控制器应用到您的响应/请求正文的默认序列化时。

要使用您的自定义映射器,请明确使用 Bean ID。

@Autowired @Qualifier("customMapper") ObjectMapper mapper;

【讨论】:

这不正是上述答案中所建议的吗?此外,如果您将ObjectMapper 注入为ObjectMapper objectMapper,则不需要@Primary @Somebody 阅读该答案中的所有 cmets。 如果你使用'spring-boot-starter-json',@Primary 是强制性的【参考方案2】:

这正是你应该使用@Qualifier注解的地方。

这个注解可以用在字段或参数上,作为自动装配时候选 bean 的限定符。它还可以用于注释其他自定义注释,然后这些注释又可以用作限定符。

【讨论】:

现在这实际上质疑我的春季知识。 spring 是否将 MyCustomMapper 和 ObjectMapper 视为同一个 bean?为什么它会影响我的整体序列化? . MyCustomMapper 可能会扩展 ObjectMapper,同时它可以实现其他接口,将其作为单独的 bean 一起限定 Here is an example 我怀疑你的情况是错误的。首先运行程序按原样,然后取消注释它所写的部分取消注释下面并再次运行。为了对其进行更多控制,我建议使用Qualifier。毕竟这是你的选择:) 尝试过的限定符。声明了两个 bean,一个为“@Primary”,一个为 Bean ID。并将修改后的 ObjectMapper 与“@Qualifier”一起使用。再一次,它弄乱了 Spring 用于所有控制器的实际隐式杰克逊。在配置中注释修改后的“@bean”可以解决问题 您分享的示例不起作用。只是扩展 ObjectMapper 会抛出 'does not override copy()' 错误

以上是关于ObjectMapper 的两个实例的主要内容,如果未能解决你的问题,请参考以下文章

spring-boot-webflux 中未使用配置的 ObjectMapper

Spring Boot:请求和响应的不同 ObjectMapper 实例

如何通过自动装配注入具有不同配置的不同ObjectMappers?

ObjectMapper SerializerCache 的单个实例中的对象过多导致内存泄漏

如何获取 Spring 4.1 使用的 Jackson ObjectMapper?

如何在不从 spring-boot-starter-web 继承的情况下在 Spring Boot 中获取 ObjectMapper 实例?