首页 文章

Jackson 2错误地序列化Java java.nio.file.Path

提问于
浏览
3

我在Eclipse 4.6.1中使用RESTEasy 3.1.0.CR3和Tomcat 8.5.6,以及JSBoss resteasy-jackson2-provider . 我有一个简单的JavaBean FooBar ,它返回一个字符串"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 简单地使用 toString()Path

这是我的项目依赖树:

+- 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 类添加注释,这是一个域模型类,它不应该与RESTful API序列化细节耦合 .

我想要一个简单的方法来挂接RESTEasy中的Jackson2并修改 Path 属性值的序列化,而无需修改我的类或为我的类编写自定义序列化程序 .

1 回答

  • 3

    这个类将覆盖默认的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;
      }
    
    }
    

    Or you can use ContextResolver also for the same which will use 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;
      }
    }
    

    无论您使用什么approch,都可以将此添加到 web.xml

    <context-param>
           <param-name>resteasy.providers</param-name>
           <param-value>package.to.CustomJacksonProvider</param-value>
        </context-param>
    

    如果您没有使用 web.xml 文件,请在JAX-RS应用程序的 Application.getClasses() 方法中返回提供程序类 .

    希望这可以帮助 .

    Edited

    此外,在此实现中您可能会错过JAXB注释支持,您必须手动配置它,因为 JacksonJaxbJsonProvider 不查找 JsonMapperConfigurator 的解析器/提供程序 . 使用 JsonMapperConfigurationCustomJackosnProvider 中的mapper以及 JacksonJaxbJsonProvider.DEAFULT_ANNOATIONS . 理想情况下,由于没有规定提供 JsonMapperConfiguration Resolver / Provider和RestEasy 's jackson provider doesn'暴露arg构造函数,提供商是最好的选择 . 由于他们做出了这个决定,理想情况下他们不应该在 ResteasyJackson2Provider 进行任何定制 . 此外,只有 ResteasyJackson2Provider 中的功能是自定义json类型,并且在类级别更好地缓存mapper .

    Updated code according to explanation

相关问题