如何在Spring Boot中为Camel配置Jackson ObjectMapper

Dav*_*rds 15 apache-camel jackson spring-boot

我正在尝试使用Jackson在Camel路由上与JSON序列化和反序列化POJO.其中一些有Java 8 LocalDate字段,我希望它们被序列化为YYYY-MM-DD字符串,而不是整数数组.

我们只对我们的Spring Boot应用程序使用Java配置,因此没有XML Camel配置.

我已经成功创建了一个ObjectMapper,它可以完成我想要的工作,我们系统的其他部分正在使用它来添加到我们的依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

这对我们的应用程序配置:

@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    return builder
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .build();
}
Run Code Online (Sandbox Code Playgroud)

示例传出REST路由:

@Component
public class MyRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        restConfiguration().component("servlet").contextPath("/mycontext")
                .port(8080).bindingMode(RestBindingMode.json);

        rest("/myendpoint)
                .get()
                .route()
                .to("bean:myService?method=myMethod()");
    }
}
Run Code Online (Sandbox Code Playgroud)

传入消息路由示例:

@Component
public class MyRouteBuilder extends RouteBuilder {

    @Autowired
    private MyBean myBean;

    @Override
    public void configure() {
        from(uri)
                .unmarshal().json(JsonLibrary.Jackson)
                .bean(myBean);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,默认情况下,Camel会创建自己的ObjectMapper实例,因此不会选择Jackson2ObjectMapperBuilder自动添加的JSR310序列化程序/反序列化程序或禁用的WRITE_DATES_AS_TIMESTAMPS功能.我已经阅读了Camel JSON文档,但它没有说明如何使用Spring配置添加自定义DataFormat,或者如何为所有类型应用全局自定义.

那么如何使用Spring Boot Java配置告诉Camel使用我的ObjectMapper?

Inn*_*nty 16

大家好消息,Spring Boot 现在支持对象映射器自动发现!只需设置此属性:

camel.dataformat.json-jackson.auto-discover-object-mapper=true
Run Code Online (Sandbox Code Playgroud)

如果设置为 true 那么 Jackson 将在注册表中查找 objectMapper

文档: https: //camel.apache.org/components/latest/dataformats/json-jackson-dataformat.html#_spring_boot_auto_configuration

日志:

INFO o.a.c.impl.engine.AbstractCamelContext   : Apache Camel 3.3.0 (CamelContext: camel-1) is starting
INFO o.a.c.c.jackson.JacksonDataFormat        : Found single ObjectMapper in Registry to use: com.fasterxml.jackson.databind.ObjectMapper@20a1b3ae
WARN o.a.c.c.jackson.JacksonDataFormat        : The objectMapper was already found in the registry, no customizations will be applied
Run Code Online (Sandbox Code Playgroud)

(警告只是表示,下面的所有其他属性都camel.dataformat.json-jackson.*将被忽略)

更新 17.08.2022

对于新版本的 Camel,因为3.15.0使用不同的属性

camel.dataformat.jackson.auto-discover-object-mapper=true
Run Code Online (Sandbox Code Playgroud)

  • 并不是说他们用camel 3.15将该属性重命名为“camel.dataformat.jackson.auto-discover-object-mapper=true” (2认同)

Cla*_*sen 6

创建JacksonDataFormatjava代码并启用/禁用所需的功能,然后在Camel路由中使用该实例。

 .unmarshal(myInstanceGoesHere).
Run Code Online (Sandbox Code Playgroud)

这是使用时的示例marshal,同样可以是适配器unmarshal

CamelContext ctx = new DefaultCamelContext();
JacksonDataFormat df = new JacksonDataFormat();

df.setModuleClassNames("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule");

ctx.addRoutes(
    new RouteBuilder() {
      @Override
      public void configure() {
        from("direct:start").marshal(df).log("Out");
      }
    });
Run Code Online (Sandbox Code Playgroud)

  • 我记录了一张票证,允许配置自定义对象映射器实例以用于数据格式:https://issues.apache.org/jira/browse/CAMEL-9275 (2认同)

Dav*_*rds 6

我已经通过单步执行Camel代码找到了解决方案.因此,虽然它可以实现我想要的功能,但它可能不适用于未来的Camel版本,因为它似乎没有文档记录且可能不受支持.

我所做的就是将以下bean添加到我的Spring配置中,除了ObjectMapper问题中的bean 之外:

@Bean(name = "json-jackson")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public JacksonDataFormat jacksonDataFormat(ObjectMapper objectMapper) {
    return new JacksonDataFormat(objectMapper, HashMap.class);
}
Run Code Online (Sandbox Code Playgroud)

需要注意的关键点:

  • JacksonDataFormat如果ObjectMapper没有unmarshal类型,则没有构造函数.但是,在默认构造函数中,HashMap.class当没有提供unmarshal类型时使用a ,所以我使用它.通过一些魔术,这似乎习惯于解组所有POJO类型.如果您还需要更多特定数据格式用于其他类,则还需要设置其他类ObjectMapper.
  • Camel似乎在bean注册表中搜索一个名为"json-jackson"的bean,因此设置Spring bean使用该名称会欺骗Camel而不是创建一个新的并使用我的.
  • 必须将bean范围设置为,SCOPE_PROTOTYPE因为REST DSL期望获取该实例DataFormat.见CAMEL-7880.