我正在开发一个需要FasterXML和ZonedDateTime的项目。必须不使用using=Deserializer.class
之类的注释,因为我们希望在所有项目中保持相同的日期格式。
话虽如此,我来这里寻求帮助,因为我无法弄清楚为什么我的Deserializer是实例化的,但它的方法deserialize()
不是调用...
这是我的配置:
序列化器:
public class ZonedDateTimeSerializer extends JsonSerializer<ZonedDateTime> {
/**
* The date time formatter to use
*/
DateTimeFormatter dtf;
/**
* Instanciate a new serializer
*
* @param dtf The datetime formatter
*/
public ZonedDateTimeSerializer(DateTimeFormatter dtf) {
System.out.println("ZonedDateTimeSerializer()");
this.dtf = dtf;
}
@Override
public void serialize(ZonedDateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
System.out.println("ZonedDateTimeSerializer::serialize()");
if (null != dateTime) {
jsonGenerator.writeString(dateTime.format(dtf));
}
}
}
反序列化器:
public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
/**
* The date time formatter to use
*/
DateTimeFormatter dtf;
/**
* Instanciate a new deserializer
*
* @param dtf The datetime formatter
*/
public ZonedDateTimeDeserializer(DateTimeFormatter dtf) {
Preconditions.checkNotNull(dtf, "Date time formatter is null");
System.out.println("ZonedDateTimeDeserializer()");
this.dtf = dtf;
}
@Override
public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
System.out.println("ZonedDateTimeDeserializer::deserialize()");
return ZonedDateTime.parse(jsonParser.getText(), dtf);
}
}
这两个在mapper提供者中添加到mapper中:
@Provider
public class JacksonConfigurator implements ContextResolver<ObjectMapper> {
private ObjectMapper mapper = new ObjectMapper();
/**
* Constructor
*/
public JacksonConfigurator() {
System.out.println("new ObjectMapperResolver()");
DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
SimpleModule xxxModule = new SimpleModule("XXXX", new Version(2, 0, 0, null))
.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer(sdf))
.addDeserializer(ZonedDateTime.class, new ZonedDateTimeDeserializer(sdf));
mapper.registerModule(xxxModule);
}
@Override
public ObjectMapper getContext(Class<?> arg0) {
return mapper;
}
}
在这里注册玻璃鱼球衣ResourceConfig;
@ApplicationPath("api")
public class ApplicationRessourceConfig extends ResourceConfig {
/**
* Define application config
*/
public ApplicationRessourceConfig() {
// File to parse
packages(true, "com.xxx.xxx");
// CDI to Jersey
register(new WebServiceBinder());
// Jackson config
register(new JacksonConfigurator());
// Role
register(RolesAllowedDynamicFeature.class);
}
}
在测试没问题之前,我无法在生产或开发中测试它。所以我做了如下测试:
public class xxxTest extends JerseyTest {
...
@Override
protected Application configure() {
...
ResourceConfig config = new ResourceConfig(...);
config.register(new JacksonConfigurator());
return config;
}
@Test
public void xxx() {
...
response.bufferEntity();
response.readEntity(EntityWithZonedDateTime.class);
...
}
}
当我在每个ZonedDateTime属性上使用注释@JsonDeserializer
时,它工作得很好但是现在,Serializer
构造函数被记录,serialize()
也被记录,事件为Deserializer
记录构造函数,但不记录deserialize()
方法。
相反,我有:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.ZonedDateTime] from String value ('2012-06-30T12:30:40.000+0000'); no single-String constructor/factory method
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@3af4e0bf; line: 1, column: 46] (through reference chain: com.xxx.xxx.resources.utils.Xxxx["beginDate"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:843)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:277)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1150)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:153)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:144)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:523)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.findDeserializeAndSet(BeanPropertyMap.java:285)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:248)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1408)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:858)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:777)
下午2点,我将在48小时内完成。无法知道为什么映射器不会尝试使用反序列化器进行desiarilize并且它会回退到字符串上。猜猜是什么......更快的xml wiki已经失败了...任何线索都是受欢迎的。
---编辑---
有关信息,请求中发送的实体如下所示:
@XmlRootElement
public class XxxOutput {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public static class XxxJson {
/* ---------- Properties ---------- */
public BigInteger id;
public String name;
public String definition;
public ZonedDateTime beginDate;
public ZonedDateTime endDate;
public ZonedDateTime creationDate;
public ZonedDateTime lastUpdate;
public Map<String, BigInteger> relateds;
/* ---------- Constructor ---------- */
public XxxJson() {}
public XxxJson(... all args ...) {
this.id = id;
...
this.relateds = relateds;
}
/* ---------- Useful methods ---------- */
public XxxJson addRelated(final Xxx related) {
...
// add the Xxx.id to the list
...
}
@Override
public String toString() {
return id.toString();
}
}
}