#spring #serialization #jackson
#весна #Сериализация #джексон
Вопрос:
Я использую Spring MVC и Jackson для де- / сериализации JSON. Но я столкнулся с проблемой сериализации даты.
По умолчанию Джексон сериализует дату как эпоху. Но я хочу сериализовать его как дату ISO (т.Е. 06-10-2011 11:00:00).
Приведенный ниже код является моей конфигурацией spring, но он не работает. Он по-прежнему возвращает дату эпохи.
Итак, мой вопрос в том, как я могу сериализовать дату, отличную от эпохи?
<!-- JSON -->
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig" factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" />
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="setSerializationInclusion" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="setDateFormat" />
<property name="arguments">
<list>
<value type="java.text.SimpleDateFormat">yyyy-MM-dd'T'HH:mm:ss.SSSZ</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="enable" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.SerializationConfig.Feature">WRITE_DATES_AS_TIMESTAMPS</value>
</list>
</property>
</bean>
Ответ №1:
Гораздо более простой способ сделать это сейчас в Spring 3.1.
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
setDateFormat(new ISO8601DateFormat());
}
}
А затем зарегистрируйте это как компонент и настройте элемент, управляемый mvc: аннотациями.
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="customObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="customObjectMapper" class="CustomObjectMapper"/>
Комментарии:
1. Обратите внимание, что при использовании Spring 3.2 и Jackson2 следует
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
также учитывать, что если у вас есть два раздела «<mvc: аннотации, управляемые>», это может привести к сбою без предупреждения 🙂2. О, и вам вообще не нужна строка «setDateFormat» — если вы отключите WRITE_DATES_AS_TIMESTAMPS, вы получите даты ISO 6801 по умолчанию.
3. @Korny. Спасибо. Не знал, что он автоматически возвращается к 8601.
4. Я обновился с Spring 3.0, чтобы сделать это, но столкнулся с проблемой времени выполнения при чтении XML. Я обнаружил, что мне пришлось изменить 3.0.xsd на 3.1.xsd в xsi: schemaLocation XML-файла, иначе я бы получил «‘mvc: аннотационный элемент’ не должен иметь элемента информации о символах или элементах [дочерние элементы]»
Ответ №2:
Решение с использованием Spring 3.1.3 и Jackson 2.1.0, которое работает для меня (на основе ответа Райана и заметок Корниса с дополнительным изменением в коде Java «SerializationConfig.Функция» -> «SerializationFeature»)
public class DateObjectMapper extends ObjectMapper {
public DateObjectMapper() {
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
Конфигурация:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="dateObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="dateObjectMapper" class="DateObjectMapper"/>
Ответ №3:
Я нашел следующее для работы с Spring Platform 2.0 (Spring 4.2) и Jackson 2.6.3
pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
</dependency>
applicationContext.xml
<mvc:annotation-driven>
<mvc:message-converters>
<beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<beans:property name="objectMapper">
<beans:bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<beans:property name="featuresToDisable">
<beans:array>
<util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS"/>
</beans:array>
</beans:property>
</beans:bean>
</beans:property>
</beans:bean>
</mvc:message-converters>
</mvc:annotation-driven>
Комментарии:
1. Большое спасибо, это потрясающе.
Ответ №4:
Я исправил свою проблему. Итак, для справки о других с аналогичной проблемой.
Я удалил следующие элементы в xml конфигурации контекста spring:
<mvc:annotation-driven/>
и
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="setDateFormat" />
<property name="arguments">
<list>
<value type="java.text.SimpleDateFormat">yyyy-MM-dd'T'HH:mm:ss.SSSZ</value>
</list>
</property>
Затем я добавил следующее:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="1" />
</bean>
и изменил следующее:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="enable" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.SerializationConfig.Feature">WRITE_DATES_AS_TIMESTAMPS</value>
</list>
</property>
в
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="disable" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.SerializationConfig.Feature">WRITE_DATES_AS_TIMESTAMPS</value>
</list>
</property>
После этого Spring смог сериализовать мою дату в json как дату ISO.
Комментарии:
1. это должно быть для гораздо более старой версии jackson, поскольку классы были перенесены из org.codehaus. джексон в com.fasterxml.jackson начиная с версии 2.0
2. @JasonHarrison Это правильно, поскольку этот вопрос был задан еще в 2011 году.