Spring MVC3.2RC1のREST APIに取り組んでいます。
Org.joda.time.DateTimeタイムスタンプを含むJPAエンティティをフェッチし、Springにそれを使用してJSONにシリアル化させます
@RequestMapping(value = "/foobar", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
追加しただけなので、SpringのデフォルトのJackson2設定を使用します
<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}
しかし、私はそれを2007-11-16T20:14:06.3Z(またはオフセット付き)のようなISO8601の日付にしたいと思います。
私の推測では、ObjectMapperにアクセスし、mapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);を設定する必要があります。しかし、使用時にObjectMapperにアクセスするにはどうすればよいですか?
<mvc:annotation-driven />
P.S. JodaTimeサポートを取得するためにUserTypeを使用してJPA/Hibernate4でオブジェクトをPostgreSQLに永続化しています。 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>
または、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());
}
}
最終的には jackson-datatype-joda を使用して動作するようになりました:
別のMaven依存関係を追加します(Jacksonバージョン番号と一致します):
<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
を無効にしても違いはないようです。
SpringでのJodaTimeシリアル化の回答とポストワーキングソリューションを要約するだけです(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>
この後、ResponseBodyのJodaTimeフィールドはJSONで「createdDate」として自動的にシリアル化されます:「2013-01-18T15:15:36.365 + 02:00」
JodaDayTimeを使用してエンティティフィールドからjacksonによって作成されたものとまったく同じb @#$ dに苦労していました。
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/
誰かが私のエンティティクラスまたはコントローラーのコードをもっと見たい場合は、コメントで質問してください。この回答に十分なコードを追加します。
私は同じ問題に苦しんでおり、app-servlet.xml
でこの方法でDateTimeのJSONへのSpringシリアル化を単純化しようとしました:
<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>
ここでは、 Java-json-client ライブラリから no.bouvet.jsonclient.spring.JsonClientJackson2ObjectMapperFactoryBean を見つけることができます。