我正在使用Spring和Jersey构建REST服务应用程序。
“响应内容类型”可以是JSON或XML,这就是我在POJO的字段上使用JAXB注释的原因,到目前为止效果很好。无需配置即可实现此功能,我只需将所需的.jars放在类路径上。
现在,我想为Java 8日期/时间对象的(反)序列化添加自定义行为,并注册杰克逊的JavaTimeModule
。
哪里是注册模块的正确位置?我知道代码片段应该是这样的:
ObjectMapper tmpMapper = new ObjectMapper();
tmpMapper.registerModule(new JavaTimeModule());
但我在哪里实际放置此代码?
我想到的是来自泽西岛的ResourceConfig
课程。它看起来像这样:
@ApplicationPath("/rest")
public class ApplicationResourceConfig extends ResourceConfig {
public ApplicationResourceConfig() {
// Not needed because since jersey 2.9 JacksonFeature implements AutoDiscoverable
// register(JacksonFeature.class);
register(WadlFeature.class);
// Registers our own request listener for monitoring purposes
register(RestServiceApplicationEventListener.class);
// Registers the package that contains our REST resources
packages(PingResource.class.getPackage().getName());
}
我现在所做的是在构造函数的底部添加以下行:
ObjectMapper tmpMapper = new ObjectMapper();
tmpMapper.registerModule(new JavaTimeModule());
JacksonJaxbJsonProvider tmpProvider = new JacksonJaxbJsonProvider();
tmpProvider.setMapper(tmpMapper);
register(tmpProvider);
DateTime转换现在有效。但是,一些JAXB行为发生了变化,导致其他bean的反序列化中断。以下是不再适用的内容:
我有超类,它定义了一个字段的getter:
public abstract class SuperClass {
@XmlElement(name = "yourField")
public abstract String getMyField();
}
(这会将字段的内部名称映射到暴露给外部的不同名称)
public class SubClass {
private String myField;
@Override
public String getMyField() {
return myField;
}
}
这种机制以前用过,我可以用定义SubClass类型的POST参数,使用如下所示的JSON片段调用该方法:
{
"yourField" : "hello world"
}
现在尝试这个时,我得到了例外:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "yourField" (class com.myProject.SubClass), not marked as ignorable (1 known property: "myField"])
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@728b1889; line: 4, column: 14] (through reference chain: com.myProject.Subclass["yourField"])
但请注意,基本的JAXB功能仍然有效,仅在此特定的超类/子类示例中。
是否明确注册JacksonJaxbJsonProvider
以某种方式改变了如何处理JAXB注释bean的默认行为?有没有办法可以检索现有的JacksonJaxbJsonProvider
(必须以某种方式隐式注册)或现有的ObjectMapper
对象并注册JavaTimeModule
而不是创建新的Mapper对象和一个新的Provider对象?