Jackson2 JSON ISO 8601 от JodaTime в Spring 3.2RC1
Я работаю над REST API в Spring MVC 3.2RC1.
Я получаю объект JPA с отметкой времени org.joda.time.DateTime в нем и пусть Spring сериализует его в JSON, используя
@RequestMapping(value = "/foobar", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
Использование стандартных настроек Jackson2 в Spring, поскольку я добавил только
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.1</version>
</dependency>
на мой POM и пусть Spring подключится сам.
Контроллер генерирует:
"created":{"year":2012,"dayOfMonth":30,"dayOfWeek":5,"era":1,"dayOfYear":335,"weekOfWeekyear":48,"weekyear":2012,"monthOfYear":11,"yearOfEra":2012,"yearOfCentury":12,"centuryOfEra":20,"millisOfSecond":39,"millisOfDay":52684039,"secondOfMinute":4,"secondOfDay":52684,"minuteOfHour":38,"minuteOfDay":878,"hourOfDay":14,"millis":1354282684039,"zone":{"uncachedZone":{"cachable":true,"fixed":false,"id":"Europe/Stockholm"},"fixed":false,"id":"Europe/Stockholm"},"chronology":{"zone":{"uncachedZone":{"cachable":true,"fixed":false,"id":"Europe/Stockholm"},"fixed":false,"id":"Europe/Stockholm"}},"afterNow":false,"beforeNow":true,"equalNow":false}
Но я бы хотел, чтобы это была дата ISO8601, такая как 2007-11-16T20: 14: 06.3Z (или со смещением).
Я предполагаю, что мне нужно получить доступ к ObjectMapper и установить mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); Но как мне получить доступ к ObjectMapper при использовании
<mvc:annotation-driven />
P.S. Я сохраняю объекты PostgreSQL с JPA/Hibernate4, используя UserType, чтобы получить поддержку JodaTime. D.S.
Обновление
Конфигурация ниже решает его для java.util.Date, но до сих пор нет кубиков для JodaTime.
<annotation-driven>
<message-converters>
<beans:bean
class="org.springframework.http.converter.StringHttpMessageConverter" />
<beans:bean
class="org.springframework.http.converter.ResourceHttpMessageConverter" />
<beans:bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<beans:property name="objectMapper">
<beans:bean
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
p:indentOutput="true" p:simpleDateFormat="yyyy-MM-dd'T'HH:mm:ss.SSSZ">
</beans:bean>
</beans:property>
</beans:bean>
</message-converters>
</annotation-driven>
Ответы
Ответ 1
Или, если вы предпочитаете делать свою конфигурацию на Java, это может выглядеть так:
@Configuration
@EnableWebMvc
public class RestConfig extends WebMvcConfigurerAdapter {
private ObjectMapper objectMapper() {
Jackson2ObjectMapperFactoryBean bean = new Jackson2ObjectMapperFactoryBean();
bean.setIndentOutput(true);
bean.setSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
bean.afterPropertiesSet();
ObjectMapper objectMapper = bean.getObject();
objectMapper.registerModule(new JodaModule());
return objectMapper;
}
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper());
return converter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(mappingJackson2HttpMessageConverter());
}
}
Ответ 2
В итоге я начал работать с jackson-datatype-joda:
Добавьте еще одну зависимость от Maven (соответствует номеру версии вашего Джексона):
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson.version}</version>
</dependency>
Затем зарегистрируйте JodaModule (который обрабатывает преобразование) в Jackson ObjectMapper (здесь сделано в Spring, но вы можете создать вспомогательный класс):
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:targetObject-ref="objectMapper" p:targetMethod="registerModule">
<property name="arguments">
<list><bean class="com.fasterxml.jackson.datatype.joda.JodaModule"/></list>
</property>
</bean>
(вам нужно указать ObjectMapper id, чтобы он мог ссылаться таким образом).
Модуль Hibernate также зарегистрирован следующим образом: https://github.com/FasterXML/jackson-module-hibernate
Обратите внимание, что вам нужно установить (Simple) DateFormat, как показано в вопросе, но отключение SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS
, похоже, не имеет никакого значения.
Ответ 3
Просто подведем итоги и опубликуем рабочее решение для сериализации JodaTime в Spring (проверено на Spring 3.2)
spring -context.xml
<bean id="objectMapper"
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
p:indentOutput="true" p:simpleDateFormat="yyyy-MM-dd'T'HH:mm:ss.SSSZ">
</bean>
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:targetObject-ref="objectMapper" p:targetMethod="registerModule">
<property name="arguments">
<list>
<bean class="com.fasterxml.jackson.datatype.joda.JodaModule" />
</list>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean
class="org.springframework.http.converter.ResourceHttpMessageConverter" />
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Зависимости Maven (com.fasterxml.jackson-версия 2.1.1)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${com.fasterxml.jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${com.fasterxml.jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${com.fasterxml.jackson-version}</version>
</dependency>
После этого ваши поля JodaTime в ResponseBody будут автоматически сериализованы в JSON как
"createdDate": "2013-01-18T15: 15: 36.365 + 02: 00"
Ответ 4
Я боролся с тем же b @# $d, созданным jackson из поля entity с joda DayTime:
modifiedOn": {
"year": 2013,
"dayOfWeek": 6,
"era": 1,
"dayOfYear": 124,
"dayOfMonth": 4,
"weekOfWeekyear": 18,
"monthOfYear": 5,
"yearOfCentury": 13,
"centuryOfEra": 20,
"millisOfSecond": 0,
"millisOfDay": 81801000,
"secondOfMinute": 21,
"secondOfDay": 81801,
"minuteOfHour": 43,
"minuteOfDay": 1363,
"weekyear": 2013,
"yearOfEra": 2013,
"hourOfDay": 22,
"millis": 1367700201000,
"zone": {
"uncachedZone": {
"cachable": true,
"fixed": false,
"id": "Europe/Belgrade"
},
"fixed": false,
"id": "Europe/Belgrade"
},
"chronology": {
"zone": {
"uncachedZone": {
"cachable": true,
"fixed": false,
"id": "Europe/Belgrade"
},
"fixed": false,
"id": "Europe/Belgrade"
}
},
"afterNow": false,
"beforeNow": true,
"equalNow": false
}
Как упоминается здесь
https://github.com/FasterXML/jackson-datatype-joda
это очень легко с Jackson 2.0, но для новичков, подобных мне, было довольно сложно понять, как заставить его работать, но, наконец, нашел рабочий фрагмент кода:
Зависимость в maven - это было просто
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.1.2</version>
</dependency>
и некоторый код из документации FasterXML
objectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
... но как его реализовать? Вот пример - новый класс:
public class JodaObjectMapper extends ObjectMapper {
public JodaObjectMapper() {
super();
registerModule(new JodaModule());
}
}
И последний шаг - добавление к spring.xml
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="net.jvw.JodaObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Итак, теперь посмотрим на созданную json
"modifiedOn": 1367701129075
наконец-то легко справиться с
Из сообщения в блоге http://vanwilgenburg.wordpress.com/2013/01/14/return-usable-joda-dates-in-json-with-jackson/
Если кто-то хочет увидеть больше кода моего класса или контроллера сущности - пожалуйста, спросите в комментарии, и я добавлю достаточный код для этого ответа.
Ответ 5
Я борюсь с той же проблемой и попытался упростить сериализацию DateTime Spring для JSON таким образом в app-servlet.xml
:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="no.bouvet.jsonclient.spring.JsonClientJackson2ObjectMapperFactoryBean"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Здесь вы можете найти no.bouvet.jsonclient.spring.JsonClientJackson2ObjectMapperFactoryBean из java-json-client