java ZonedDateTime 的 Jackson 反序列化问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34764355/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:18:31  来源:igfitidea点击:

Hymanson deserialization issue for ZonedDateTime

javajsonspringHymansonjsr310

提问by tunix

I've the following field in a class I use during deserialization of a service that I'm consuming.

我在我正在消费的服务的反序列化期间使用的类中有以下字段。

private ZonedDateTime transactionDateTime;

The service I'm consuming may return a Date or DateTime using the pattern: yyyy-MM-dd'T'HH:mm:ss.SSSZ

我正在使用的服务可能会使用以下模式返回 Date 或 DateTime: yyyy-MM-dd'T'HH:mm:ss.SSSZ

Let me give 2 examples of what the service returns:

让我举两个服务返回的例子:

  • 2015-11-18T18:05:38.000+0200
  • 2015-11-18T00:00:00.000+0200
  • 2015-11-18T18:05:38.000+0200
  • 2015-11-18T00:00:00.000+0200

While first one works well, the latter causes the following exception to be thrown during deserialization:

虽然第一个运行良好,但后者会导致在反序列化过程中抛出以下异常:

java.time.format.DateTimeParseException: Text '2015-11-18T00:00:00.000+0200' could not be parsed at index 23

java.time.format.DateTimeParseException:无法在索引 23 处解析文本“2015-11-18T00:00:00.000+0200”

I'm using;

我正在使用;

  • Spring Boot 1.3.1
  • Hymanson 2.6.4 (with JSR310 module included)
  • 弹簧靴 1.3.1
  • Hymanson 2.6.4(包含 JSR310 模块)

Does this require a custom deserialization class?

这是否需要自定义反序列化类?

采纳答案by tunix

Earlier in the code I was using the field with @JsonFormatannotation but removed that as I thought it was meant for serialization only like the JavaDocs suggest.

在代码的早些时候,我使用带有@JsonFormat注释的字段,但删除了它,因为我认为它仅用于序列化,就像 JavaDocs 建议的那样。

Turned out that I needed add back that annotation. And the real issue was that the 3rd party service response was indeed wrong (it was missing a wrapper element in the XML) which caused the deserialisation to fail. The error was:

原来我需要加回那个注释。真正的问题是第 3 方服务响应确实是错误的(它在 XML 中缺少包装元素)导致反序列化失败。错误是:

com.fasterxml.Hymanson.databind.JsonMappingException: Can not instantiate value of type [simple type, class com.foo.bar.adapter.john.model.account.UserAccount] from String value ('2015-11-18T00:00:00.000+0200'); no single-String constructor/factory method

com.fasterxml.Hymanson.databind.JsonMappingException:无法从字符串值('2015-11-18T00:00: 00.000+0200'); 没有单字符串构造函数/工厂方法

The field is written like below:

该字段的写法如下:

@JsonFormat(pattern = Constants.DATETIME_FORMAT)
@HymansonXmlProperty(localName = "transactionDate")
private ZonedDateTime transactionDateTime;

Also I had to add @JsonRootName("transaction")to the class of this field because the object is wrapped into a collection.

此外,我必须添加@JsonRootName("transaction")到该字段的类中,因为该对象被包装到一个集合中。

回答by Ricardo Vila

You can use annotations like:

您可以使用以下注释:

@JsonSerialize(using = MyCustomJsonDateSerializer.class)

or

或者

@JsonDeserialize(using = MyCustomJsonDateDeserializer.class)

To customize how Hymanson parses Dates. Those custom Serializer and Deserializer must extend JsonSerializer and JsonDeserializer. For example:

自定义 Hymanson 解析日期的方式。那些自定义的 Serializer 和 Deserializer 必须扩展 JsonSerializer 和 JsonDeserializer。例如:

public class MyCustomJsonDateSerializer extends JsonSerializer<Date> {

    @Override
    public void serialize(Date date, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        jgen.writeString(date != null ? ISODateTimeFormat.dateTime().print(new DateTime(date)) : null);
      }
}

回答by Jiajun Cui

Hymanson deserialize will by default to by pass the timezone infor and use ctx timezone to overrride it ,which all ISO8601 will ends to UTC

Hymanson 反序列化将默认绕过时区信息并使用 ctx 时区覆盖它,所有 ISO8601 都将结束为 UTC

this feature can be turned off by ,if you are on spring

如果您在春季,可以通过以下方式关闭此功能

spring.Hymanson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE=false

回答by Vladimir Rozhkov

I've used

我用过

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
private ZonedDateTime startDate;

plus Hymanson-datatype-jsr310library, obviously.

Hymanson-datatype-jsr310显然,加上图书馆。

This solution is described in Hymanson deserialize ISO8601 formatted date-time into Java8 Instant

Hymanson deserialize ISO8601 formatted date-time into Java8 Instant描述了这个解决方案