我正在尝试使用Jackson在Camel路由上与JSON序列化和反序列化POJO。其中一些有Java 8 LocalDate字段,我希望它们被序列化为YYYY-MM-DD字符串,而不是整数数组。
我们只为我们的Spring Boot应用程序使用Java配置,因此没有XML Camel配置。
我已成功创建了一个ObjectMapper,它可以实现我想要的功能,我们系统的其他部分通过将它添加到我们的依赖项中来使用它:
def price(self):
if self.amazon_url:
url = self.amazon_url
source_code = requests.get(url)
code = html.fromstring(source_code.text)
prices = code.xpath('//span[@id="priceblock_ourprice"]/text()')
eur = prices[0].replace("EUR ", "")
nospace = eur.replace(" ", "")
nodown = nospace.replace("\n", "")
end = nodown.replace(",", ".")
return float(end)
else:
return 0
这是我们的应用程序配置:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
示例传出REST路由:
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return builder
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
传入消息路由示例:
@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()");
}
}
但是,默认情况下,Camel会创建自己的ObjectMapper实例,因此不会选择@Component
public class MyRouteBuilder extends RouteBuilder {
@Autowired
private MyBean myBean;
@Override
public void configure() {
from(uri)
.unmarshal().json(JsonLibrary.Jackson)
.bean(myBean);
}
}
自动添加的JSR310序列化程序/反序列化程序或禁用的Jackson2ObjectMapperBuilder
功能。我已经阅读了Camel JSON文档,但没有说明如何使用Spring配置添加自定义DataFormat,或者如何为所有类型应用全局自定义。
那么我怎样才能告诉Camel使用我的ObjectMapper,只使用Spring Boot Java配置?
答案 0 :(得分: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);
}
需要注意的关键点:
JacksonDataFormat
的构造函数需要ObjectMapper
而没有unmarshal类型。但是,在默认构造函数中,当没有提供unmarshal类型时使用HashMap.class
,所以我使用它。通过一些魔术,这似乎习惯于解组所有POJO类型。如果您还需要其他类的更具体的数据格式,则还需要在其中设置ObjectMapper
。SCOPE_PROTOTYPE
,因为REST DSL希望获得DataFormat
的新实例。见CAMEL-7880。答案 1 :(得分:3)
在java代码中创建<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageview_fullscreen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher" />
</RelativeLayout>
并启用/禁用所需的功能,然后在Camel路由中使用该实例。
JacksonDataFormat
答案 2 :(得分:2)
使用Spring和Camel 2.18.1,我可以通过添加以下依赖项来实现相同的目的:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.6.1</version>
</dependency>
并在CamelContextConfiguration
类中,自动装配JacksonDataFormat
以配置类路径模块的发现和序列化选项的配置:
@Configuration
public class CamelContextConfig implements CamelContextConfiguration {
@Autowired
public JacksonDataFormat jacksonDataFormat;
@Override
public void beforeApplicationStart(CamelContext camelContext) {
}
@Override
public void afterApplicationStart(CamelContext camelContext) {
jacksonDataFormat
.getObjectMapper()
.findAndRegisterModules()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
答案 3 :(得分:2)
我设法使用org.apache.camel:camel-jackson-starter:2.20.0
它通过Spring应用程序属性公开了一些有用的ObjectMapper属性。例如,可以从application.yaml或application.properties文件直接设置WRITE_DATES_AS_TIMESTAMPS。
查找JacksonDataFormatConfiguration类以获取更多详细信息。
我还需要使用一些Mixins,所以我仍然需要配置Camel来使用Spring的ObjectMapper。我最终得到了这个:
配置bean:
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.mixIn(Person.class, PersonMixin.class);
}
}
}
application.yaml:
camel:
dataformat:
json-jackson:
disable-features: WRITE_DATES_AS_TIMESTAMPS
object-mapper: jacksonObjectMapper
其中jacksonObjectMapper
是由配置的Jackson2ObjectMapperBuilder构建的ObjectMapper bean的名称
答案 4 :(得分:1)
到目前为止,只有@ david-edwards的建议对我有用。我首先使用id:“json-jackson”
定义了一个数据格式bean<bean id="json-jackson" class="com.mydomain.JacksonDataFormatExt" />
然后是格式类:
public class JacksonDataFormatExt extends JacksonDataFormat{
public JacksonDataFormatExt(){
super();
setPrettyPrint(true);
setEnableFeatures(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS.name());
SimpleModule s = new SimpleModule();
s.addSerializer(CustomEnum.class, new CustomEnumSerializer());
addModule(s);
}
}
CustomEnumSerializer类:
public class CustomEnumSerializer extends JsonSerializer<CustomEnum> {
@Override
public void serialize(CustomEnumvalue, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
String stringValue = value.getNlsText();
if(stringValue != null && !stringValue.isEmpty() && !stringValue.equals("null")) {
jgen.writeString(stringValue);
} else {
jgen.writeNull();
}
}
}
答案 5 :(得分:1)
如果有人想知道如何使用版本中的修复程序。 2.17 .. 我使用这个xml配置工作了:
<camel:camelContext id="defaultCamelContext">
.....
<camel:dataFormats>
<camel:json id="json" library="Jackson" objectMapper="myObjectMapper"/>
</camel:dataFormats>
</camel:camelContext>
..其中myObjectMapper是ObjectMapper类型的spring bean的名称
答案 6 :(得分:1)
我通过在pom中包含杰克逊依赖项来解决
RealFloat
现在,只需在路由配置中添加JacksonDataFormat
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>${camel.version}</version>
</dependency>
答案 7 :(得分:0)
如果Camel在那里给你带来麻烦,我会直接使用bean:
只需创建一个可以进行编组和解组的小型Json实用程序,并将预配置的ObjectMapper自动装入其中。
利用Camels很棒的Spring bean集成来调用你的实用程序并转换路由中的Message,例如:
from(uri)
.unmarshal().json(JsonLibrary.Jackson)
.beanRef("jsonUtil", "unmarshal")
.bean(myBean);
答案 8 :(得分:0)
我无法使用任何示例。有点失望的是,阅读变通方法非常复杂。
在我看来,camel应该可以通过使用应用程序附带的相同Jackson bean来轻松使用Spring默认对象映射器。
我放弃使用.json()
并将其换成处理器。
如下所示,它使用了Spring提供的objectMapper。
<强>路线强>
from(CONSUME_TAG)
.process("jsonProcessor")
.to("direct:anotherRoute")
.end();
通用处理器注意这是如何自动启动spring引导objectMapper bean。
@Component
public class JsonProcessor implements Processor {
@Autowired
ObjectMapper objectMapper;
@Override
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(objectMapper.writeValueAsString(exchange.getIn().getBody()));
}
}
答案 9 :(得分:0)
大家好消息,Spring Boot现在支持对象映射器自动发现!只需设置此属性:
camel.dataformat.json-jackson.auto-discover-object-mapper=true
如果设置为true,则Jackson将在注册表中查找objectMapper
日志:
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
(警告只是表示,您在camel.dataformat.json-jackson.*
下的所有其他属性都将被忽略)