【问题标题】:Java 8 LocalDate conversion with Jackson does not work使用 Jackson 的 Java 8 LocalDate 转换不起作用
【发布时间】:2016-06-28 18:02:02
【问题描述】:

我面临一个众所周知的问题,但没有任何解决方案适合我。任何快速帮助将不胜感激。

从 MVC 控制器,我正在调用 REST 服务,它返回模型对象,其中 LocalDate 作为字段之一。 JacksonJAXbJSONProvider 不解析 Localdate 对象。我编写了自定义映射器,如下所示,并在pom.xml 中添加了依赖项。还添加了其他所需的依赖项(jackson databind、core、annotation)

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.6.1</version>
</dependency>

自定义ObjectMapper类:

public class LocalDateObjectMapperContextResolver extends ObjectMapper{
    @Provider
    public LocalDateObjectMapperContextResolver() {

       registerModule(new JavaTimeModule());
       //findAndRegisterModules();
       configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

}

这是在Java 8 LocalDate Jackson format 中建议的

我的 spring.xml(包含 MVC 控制器等的配置)已经配置了一个映射器,它会自动进行如下转换

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" 
            p:objectMapper-ref="myobjectMapper"/>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" 
            p:objectMapper-ref="objectMapper"/>
    </mvc:message-converters>
</mvc:annotation-driven>

<bean id="objectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
<bean id="myobjectMapper" class="mypackage.LocalDateObjectMapperContextResolver"/>

下面是连接到 REST 服务的存根文件。在上面没有工作后,我也尝试提供如下提供者,但这里也没有运气。

<jaxrs:client id="testclient"
    serviceClass="package1.RESTService"
    username="abc"
    password="abc"
    address="$serviceURL">

    <jaxrs:features>
        <bean class="org.apache.cxf.transport.common.gzip.GZIPFeature"/>
        <cxf:logging/>
    </jaxrs:features>

    <jaxrs:providers>
        <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>
        <bean class="mypackage.LocalDateObjectMapperContextResolver"/>
    </jaxrs:providers>

</jaxrs:client> 

现在如何配置我刚刚编写的上下文解析器,以便能够转换 LocalDate。

我做错了什么?

我遇到了异常

No suitable constructor found for type [simple type, class java.time.LocalDate]: can not instantiate from JSON object (need to add/enable type information?)

【问题讨论】:

  • 为什么在 Spting 上下文中同时声明自定义和原始 ObjectMapper?您的自定义已经扩展了 ObjectMapper,因此您只需要声明您的自定义对象映射器。选择消息转换器并使用错误的对象映射器时,Spring 可能会混淆。
  • 感谢马特的回复,我同意你的论点。但我这样做是有原因的,我正在努力增强现有应用程序,其中许多其他 mvc 控制器使用默认的一个(来自“codehaus”),我正在扩展的一个来自“fasterxml”(支持“LocalDate”)和我将它传递给'MappingJackson2HttpMessageConverter'让我尝试仅测试视图以查看它是否有效
  • 好的,所以您同时使用了 2 个不同版本的 Jackson?这通常是一种不好的做法,即使类位于不同的包中。您应该尝试删除旧版本和其他 ObjectMapper 来清除它。
  • 我在删除旧的后尝试过,我仍然看到同样的问题。我注册错了吗?我的意思是它应该是服务器端(生成 JSON 响应的 REST 服务)还是我正在读取响应的客户端。我还尝试注册使用服务器端和客户端提供者注释的 CustomContextResolver,但它们都不起作用。解析器的 getContext() 方法在转换期间永远不会被调用。知道为什么吗?
  • 解决了。这是我的代码。希望它对某人有所帮助。 coderanch.com/t/667353/tools/Java-LocalDate-Jackson-format

标签: json jackson jax-rs


【解决方案1】:

我解决了。扩展 ObjectMapper,创建新模块,为其添加序列化器和反序列化器,最后将模块注册到 Objectmapper 并将 objectmapper 作为第一个参数传递给 JacksonJaxbJsonProvider 构造函数,传递的第二个参数是默认注释。 下面是我的代码。

    public class MyObjectMapper extends ObjectMapper {

public MyObjectMapper() {
    SimpleModule sm = new SimpleModule("SomeName", new Version(1,1,1,""));
    sm.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
        @Override
        public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            ToStringSerializer.instance.serialize(value, jgen, provider);
        }
    });
    sm.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            ToStringSerializer.instance.serialize(value, jgen, provider);
       }
    });
    sm.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() {
        @Override
        public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            return LocalDate.parse(jp.getText());
        }
    });
    sm.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
        @Override
        public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            return LocalDateTime.parse(jp.getText());
        }
    });
    registerModule(sm);
}

服务器端配置:

    <bean id="mapper" class="mymapperpkg.MyObjectMapper"/>

<jaxrs:server>
......
.....
<jaxrs:serviceBeans>....</jaxrs:serviceBeans>
......
......

<bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider">
                <constructor-arg index="0" ref="mapper"/>
                <constructor-arg index="1">
                    <util:constant static-field="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS"/>
                </constructor-arg>
            </bean> -->

</jaxrs:server>

客户端配置

   <bean id="mapper" class="mymapperpkg.MyObjectMapper"/>

 <jaxrs:client id="deliveryItemClient"
                 serviceClass="servicepkg.YourRESTServiceClass"
                 username="adadsad"
                 password="asdasdasd"
                 address="adresss to deployed service">


        <jaxrs:providers>
            <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider">
                <constructor-arg index="0" ref="mapper"/>
                <constructor-arg index="1">
                    <util:constant static-field="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS"/>
                </constructor-arg>
            </bean>
        </jaxrs:providers>

    </jaxrs:client>

这是 REST 应用程序生成 LocalDate 的时间。

如果 REST 应用程序正在使用 LocalDate,您可以编写 ParamHanlder 将 json 字符串解析回 LocalDate,如下所示并在下面注册 jaxrs 中的提供者:服务器

MyCustomParamHandler implements Paramhandler<Localdate>{

LocalDate fromString(String jsonString){
          return LocalDate.parse(jsonString);
    }
}

干杯!

【讨论】:

    猜你喜欢
    • 2015-11-07
    • 2014-10-21
    • 2023-03-20
    • 2017-12-27
    • 2017-11-30
    • 2012-09-23
    • 1970-01-01
    • 2014-10-30
    • 2015-06-28
    相关资源
    最近更新 更多