我正在尝试编组包含ISO格式的时间戳的响应:
{
...
"time" : "2014-07-02T04:00:00.000000Z"
...
}
进入我的域模型对象中的ZonedDateTime
字段。最终它是有效的,如果我使用在下面的片段中评论的解决方案。在SO上有很多类似的问题,但我想得到一个具体的答案
使用JacksonJsonProvider
和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>>(){});
答案 0 :(得分:6)
如果我使用在以下代码段中注释的解决方案,它最终会起作用。
首先,你在列表中缺少一个依赖项,你也有,这就是问题所在。
jersey-media-json-jackson
此模块取决于具有JacksonJsonProvider
的本机Jackson模块。当您注册JacksonFeature
(jersey-media-json-jackson
附带)时,它会注册自己的JacksonJaxbJsonProvider
,这似乎优先于您提供的任何内容。
当您使用ContextResolver
时,JacksonJsonProvider
实际查找ContextResolver
并使用它来解析ObjectMapper
。这就是它起作用的原因。无论您是使用JacksonFeature
还是注册了自己的JacksonJsonProvider
(没有为其配置ObjectMapper
),ContextResovler
都可以使用。
关于jersey-media-json-jackson
模块的另一个问题是,它参与了泽西岛的auto-discoverable机制,它注册了JacksonFeature
jersey-media-json-jackson
。因此,即使您没有明确注册它,它仍然会被注册。避免注册的唯一方法是:
jackson-jaxrs-json-provider
。只需使用Jackson本机模块jersey-media-json-jackson
即可。尽管如此,JacksonJaxbJsonProvider
在原生模块之上添加了一些功能,所以你会丢失这些功能。 Haven未经过测试,但似乎如果您使用JacksonJsonProvider
代替JacksonJaxbJsonProvider
,它可能会有效。如果查看source for the JacksonFeature
,您会看到它检查已注册的JacksonJaxbJsonProvider
。如果有,它就不会注册它自己的。
我对此不确定的一件事是可自动发现的。注册的顺序,如果它会影响您是否抓住您注册的k[number]
。你可以试试的东西。
答案 1 :(得分:2)
来自我的宠物项目:
<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;
}
}
答案 2 :(得分:1)
杰克逊配置看起来很好,我尝试了以下内容并且能够反序列化该值:
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
实例。您可以尝试按照here所述进行配置。