私はISO形式のタイムスタンプを含む応答をそのようにマーシャリングしようとしています:
{
...
"time" : "2014-07-02T04:00:00.000000Z"
...
}
ドメインモデルオブジェクトのZonedDateTime
フィールドに入力します。最終的には、次のスニペットでコメントされているソリューションを使用すれば機能します。SOにも同様の質問がたくさんありますが、JacksonJsonProvider
with ObjectMapper + JavaTimeModule
?
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
JacksonJsonProvider provider = new JacksonJsonProvider(mapper);
Client client = ClientBuilder.newBuilder()
// .register(new ObjectMapperContextResolver(){
// @Override
// public ObjectMapper getContext(Class<?> type) {
// ObjectMapper mapper = new ObjectMapper();
// mapper.registerModule(new JavaTimeModule());
// return mapper;
// }
// })
.register(provider)
.register(JacksonFeature.class)
.build();
私が得るエラー:
javax.ws.rs.client.ResponseProcessingException: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of Java.time.ZonedDateTime: no String-argument constructor/factory method to deserialize from String value ('2017-02-24T20:46:05.000000Z')
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@53941c2f
プロジェクトの依存関係は次のとおりです。
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.8.7'
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.7'
compile 'com.fasterxml.jackson.core:jackson-core:2.8.7'
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.7'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.7'
compile 'org.glassfish.jersey.core:jersey-client:2.25.1'
編集
逆シリアル化はここで行われます:
CandlesResponse<BidAskCandle> candlesResponse = webTarget.request()
.header(HttpHeaders.AUTHORIZATION,"Bearer "+token)
.accept(MediaType.APPLICATION_JSON)
.get(new GenericType<CandlesResponse<BidAskCandle>>(){});
最終的には、次のスニペットでコメントされているソリューションを使用すれば機能します。
まず、リストに依存関係がありません。これも問題です。
jersey-media-json-jackson
このモジュールは、JacksonJsonProvider
を持つネイティブJacksonモジュールに依存しています。 JacksonFeature
(jersey-media-json-jackson
に付属)を登録すると、独自のJacksonJaxbJsonProvider
が登録されます。これは、指定したものよりも優先されるようです。
ContextResolver
を使用すると、JacksonJsonProvider
は実際にそのContextResolver
を検索し、それを使用してObjectMapper
を解決します。それが機能する理由です。 JacksonFeature
を使用した場合でも、独自のJacksonJsonProvider
を登録した場合でも(ObjectMapper
を構成せずに)ContextResovler
が機能します。
jersey-media-json-jackson
モジュールについてもう1つ、ジャージの auto-discoverable メカニズムに参加し、JacksonFeature
を登録します。したがって、明示的に登録しなかった場合でも、登録されます。登録されないようにする唯一の方法は次のとおりです。
jersey-media-json-jackson
は使用しないでください。 Jacksonネイティブモジュールjackson-jaxrs-json-provider
を使用するだけです。ただし、jersey-media-json-jackson
を使用すると、ネイティブモジュールの上にいくつかの機能が追加されるため、これらの機能は失われます。テストはしていませんが、JacksonJaxbJsonProvider
の代わりにJacksonJsonProvider
を使用すると、動作する可能性があるようです。 JacksonFeature
のソース を見ると、すでに登録されているJacksonJaxbJsonProvider
をチェックしていることがわかります。存在する場合、それ自体は登録されません。
これについて私が確信していないことの1つは、自動検出可能です。登録されたJacksonJaxbJsonProvider
をキャッチするかどうかに影響する場合は、登録された順序。テストできる何か。
私のペットプロジェクトから:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
public WebTarget getTarget(URI uri) {
Client client = ClientBuilder
.newClient()
.register(JacksonConfig.class);
return client.target(uri);
}
どこ
@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper> {
private final ObjectMapper objectMapper;
public JacksonConfig() {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
@Override
public ObjectMapper getContext(Class<?> aClass) {
return objectMapper;
}
}
ジャクソンの設定は問題ないようです。私は次のことを試して、値を逆シリアル化することができました。
_public class Test {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
Model model = mapper.readValue("{\"time\" : \"2014-07-02T04:00:00.000000Z\"}", Model.class);
System.out.println(model.getTime());
}
}
class Model{
private ZonedDateTime time;
public ZonedDateTime getTime() {
return time;
}
public void setTime(ZonedDateTime time) {
this.time = time;
}
}
_
mapper.registerModule(new JavaTimeModule());
をコメントアウトすることで再現できます。したがって、ジャージークライアントはカスタムmapper
インスタンスを使用していないようです。説明されているように設定してみてください ここ 。