Jackson 2 错误地序列化 Java java.nio.file.Path
Jackson 2 incorrectly serializing Java java.nio.file.Path
我在 Eclipse 4.6.1 中使用带有 Tomcat 8.5.6 的 RESTEasy 3.1.0.CR3,以及 JSBoss resteasy-jackson2-provider。我有一个简单的 JavaBean FooBar
returns 一个字符串 "ID" 和一个 java.nio.file.Path
"path".
Jackson 使它很容易序列化为 JSON。在我的 JAX-RS 资源中,我只是指定 @Produces("application/json; charset=UTF-8")
。但是 Jackson 没有使用 Path.toString()
。相反,它似乎在使用 Path.toURI().toString()
或其他东西:
{
"id": "foo",
"path": "file:///C:/Users/jdoe/bar"
}
为什么!??更重要的是,我怎样才能让 Jackson 简单地使用 Path
的 toString()
版本?
这是我的项目依赖关系树:
+- com.google.code.findbugs:jsr305:jar:3.0.1:provided
+- com.google.guava:guava:jar:20.0:compile
+- javax.ws.rs:javax.ws.rs-api:jar:2.0.1:provided
+- org.jboss.resteasy:resteasy-jaxrs:jar:3.1.0.CR3:compile
| +- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.0_spec:jar:1.0.1.Beta1:compile
| +- org.jboss.resteasy:resteasy-jaxrs-services:jar:3.1.0.CR3:compile
| +- org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec:jar:1.0.0.Final:compile
| +- javax.activation:activation:jar:1.1.1:compile
| +- org.apache.httpcomponents:httpclient:jar:4.5.2:compile
| | +- org.apache.httpcomponents:httpcore:jar:4.4.4:compile
| | +- commons-logging:commons-logging:jar:1.2:compile
| | \- commons-codec:commons-codec:jar:1.9:compile
| +- commons-io:commons-io:jar:2.5:compile
| +- net.jcip:jcip-annotations:jar:1.0:compile
| \- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
+- org.jboss.resteasy:resteasy-servlet-initializer:jar:3.1.0.CR3:compile
+- org.jboss.resteasy:resteasy-jackson2-provider:jar:3.1.0.CR3:compile
| +- com.fasterxml.jackson.core:jackson-core:jar:2.8.3:compile
| +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.3:compile
| +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.3:compile
| \- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.8.3:compile
| +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.8.3:compile
| \- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.8.3:compile
+- junit:junit:jar:4.12:test
| \- org.hamcrest:hamcrest-core:jar:1.3:test
\- org.hamcrest:hamcrest-library:jar:1.3:test
请注意,不 我可以为我的 FooBar
class 添加注释,这是一个领域模型 class应该与 RESTful API 序列化细节无关。
我想要一种简单的方法来连接到 RESTEasy 中的 Jackson2 并修改 Path
属性 值的序列化,而无需修改我的 class 或为我的 [= 编写自定义序列化程序40=].
这个 class 将覆盖默认的 Jackson2JsonProvider 帮助您根据需要配置 ObjectMapper,例如 Path.class 的序列化器从 NioPathSerializer 覆盖到 ToStringSerializer。
@Provider
@Consumes({"application/*+json", "text/json"})
@Produces({"application/*+json", "text/json"})
public class CustomJacksonProvider extends JacksonJsonProvider {
public CustomJacksonProvider(){
super(configureMapper(new ObjectMapper()));
}
public static ObjectMapper configureMapper(ObjectMapper mapper) {
SimpleModule m = new SimpleModule("PathToString");
m.addSerializer(Path.class,new ToStringSerializer());
mapper.registerModule(m);
return mapper;
}
}
或者您也可以将 ContextResolver 用于将使用 ResteasyJackson2Provider(RestEasy default)
@Provider
@Consumes({"application/*+json", "text/json"})
@Produces({"application/*+json", "text/json"})
public class CustomJacksonProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper;
public CustomJacksonProvider(){
mapper = new JsonMapperConfigurator(new ObjectMapper(), JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS)
.getConfiguredMapper();
SimpleModule m = new SimpleModule("PathToString");
m.addSerializer(Path.class, new ToStringSerializer());
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
无论您使用何种方法,都将此添加给您web.xml
:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>package.to.CustomJacksonProvider</param-value>
</context-param>
如果您没有使用 web.xml
文件,return 您的 JAX-RS 应用程序的 Application.getClasses()
方法中的提供程序 class。
希望这对您有所帮助。
已编辑:
此外,您可能会错过此实现中的 JAXB 注释支持,您必须手动配置它,因为 JacksonJaxbJsonProvider
不会查找 JsonMapperConfigurator
的 Resolver/provider。在 CustomJackosnProvider
和 JacksonJaxbJsonProvider.DEAFULT_ANNOATIONS
中将 JsonMapperConfiguration
与映射器一起使用。理想情况下,由于没有规定提供 JsonMapperConfiguration
Resolver/Provider 并且 RestEasy 的 jackson 提供者不公开 arg 构造函数,提供者是最好的选择。既然他们做出了这个决定,理想情况下他们不应该在 ResteasyJackson2Provider
中进行任何定制。此外,ResteasyJackson2Provider
中只有功能是自定义 json 类型和更好的 class 级别的映射器缓存。
根据说明更新了代码
我在 Eclipse 4.6.1 中使用带有 Tomcat 8.5.6 的 RESTEasy 3.1.0.CR3,以及 JSBoss resteasy-jackson2-provider。我有一个简单的 JavaBean FooBar
returns 一个字符串 "ID" 和一个 java.nio.file.Path
"path".
Jackson 使它很容易序列化为 JSON。在我的 JAX-RS 资源中,我只是指定 @Produces("application/json; charset=UTF-8")
。但是 Jackson 没有使用 Path.toString()
。相反,它似乎在使用 Path.toURI().toString()
或其他东西:
{
"id": "foo",
"path": "file:///C:/Users/jdoe/bar"
}
为什么!??更重要的是,我怎样才能让 Jackson 简单地使用 Path
的 toString()
版本?
这是我的项目依赖关系树:
+- com.google.code.findbugs:jsr305:jar:3.0.1:provided
+- com.google.guava:guava:jar:20.0:compile
+- javax.ws.rs:javax.ws.rs-api:jar:2.0.1:provided
+- org.jboss.resteasy:resteasy-jaxrs:jar:3.1.0.CR3:compile
| +- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.0_spec:jar:1.0.1.Beta1:compile
| +- org.jboss.resteasy:resteasy-jaxrs-services:jar:3.1.0.CR3:compile
| +- org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec:jar:1.0.0.Final:compile
| +- javax.activation:activation:jar:1.1.1:compile
| +- org.apache.httpcomponents:httpclient:jar:4.5.2:compile
| | +- org.apache.httpcomponents:httpcore:jar:4.4.4:compile
| | +- commons-logging:commons-logging:jar:1.2:compile
| | \- commons-codec:commons-codec:jar:1.9:compile
| +- commons-io:commons-io:jar:2.5:compile
| +- net.jcip:jcip-annotations:jar:1.0:compile
| \- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
+- org.jboss.resteasy:resteasy-servlet-initializer:jar:3.1.0.CR3:compile
+- org.jboss.resteasy:resteasy-jackson2-provider:jar:3.1.0.CR3:compile
| +- com.fasterxml.jackson.core:jackson-core:jar:2.8.3:compile
| +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.3:compile
| +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.3:compile
| \- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.8.3:compile
| +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.8.3:compile
| \- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.8.3:compile
+- junit:junit:jar:4.12:test
| \- org.hamcrest:hamcrest-core:jar:1.3:test
\- org.hamcrest:hamcrest-library:jar:1.3:test
请注意,不 我可以为我的 FooBar
class 添加注释,这是一个领域模型 class应该与 RESTful API 序列化细节无关。
我想要一种简单的方法来连接到 RESTEasy 中的 Jackson2 并修改 Path
属性 值的序列化,而无需修改我的 class 或为我的 [= 编写自定义序列化程序40=].
这个 class 将覆盖默认的 Jackson2JsonProvider 帮助您根据需要配置 ObjectMapper,例如 Path.class 的序列化器从 NioPathSerializer 覆盖到 ToStringSerializer。
@Provider
@Consumes({"application/*+json", "text/json"})
@Produces({"application/*+json", "text/json"})
public class CustomJacksonProvider extends JacksonJsonProvider {
public CustomJacksonProvider(){
super(configureMapper(new ObjectMapper()));
}
public static ObjectMapper configureMapper(ObjectMapper mapper) {
SimpleModule m = new SimpleModule("PathToString");
m.addSerializer(Path.class,new ToStringSerializer());
mapper.registerModule(m);
return mapper;
}
}
或者您也可以将 ContextResolver 用于将使用 ResteasyJackson2Provider(RestEasy default)
@Provider
@Consumes({"application/*+json", "text/json"})
@Produces({"application/*+json", "text/json"})
public class CustomJacksonProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper;
public CustomJacksonProvider(){
mapper = new JsonMapperConfigurator(new ObjectMapper(), JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS)
.getConfiguredMapper();
SimpleModule m = new SimpleModule("PathToString");
m.addSerializer(Path.class, new ToStringSerializer());
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
无论您使用何种方法,都将此添加给您web.xml
:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>package.to.CustomJacksonProvider</param-value>
</context-param>
如果您没有使用 web.xml
文件,return 您的 JAX-RS 应用程序的 Application.getClasses()
方法中的提供程序 class。
希望这对您有所帮助。
已编辑:
此外,您可能会错过此实现中的 JAXB 注释支持,您必须手动配置它,因为 JacksonJaxbJsonProvider
不会查找 JsonMapperConfigurator
的 Resolver/provider。在 CustomJackosnProvider
和 JacksonJaxbJsonProvider.DEAFULT_ANNOATIONS
中将 JsonMapperConfiguration
与映射器一起使用。理想情况下,由于没有规定提供 JsonMapperConfiguration
Resolver/Provider 并且 RestEasy 的 jackson 提供者不公开 arg 构造函数,提供者是最好的选择。既然他们做出了这个决定,理想情况下他们不应该在 ResteasyJackson2Provider
中进行任何定制。此外,ResteasyJackson2Provider
中只有功能是自定义 json 类型和更好的 class 级别的映射器缓存。
根据说明更新了代码