【问题标题】:How to deserialize date '2017-01-01T00:00:59.000UTC'如何反序列化日期'2017-01-01T00:00:59.000UTC'
【发布时间】:2021-04-29 07:37:12
【问题描述】:

尝试使用 json 文件中的特定模式反序列化日期。
我想从 json 文件接收的对象:

@Data
public class MyClass {
  @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")
  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
  private LocalDateTime date;
}

Json 文件:

{
  "date" : "2017-01-01T00:00:59.000UTC"
}

代码示例我想如何接收它:

ObjectMapper mapper = new ObjectMapper();
MyClass clazz = mapper.readValue(new File("MyFile.json"), MyClass.class);

实际结果:

com.fasterxml.jackson.databind.exc.InvalidFormatException: 
Cannot deserialize value of type `java.time.LocalDateTime` from String "2017-01-01T00:00:59.000UTC":
Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) 
Text '2017-01-01T00:00:59.000UTC' could not be parsed, unparsed text found at index 23
at [Source: (File); line: 2, column: 11] (through reference chain: com.example.MyClass["date"])

如何反序列化当前的日期模式?

【问题讨论】:

  • 2017-01-01T00:00:59.000UTC 是一种特殊的混合格式。国际标准ISO 8601有什么问题?

标签: java json date


【解决方案1】:

您使用的日期格式不正确。

代替:yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'

应该是:yyyy-MM-dd'T'HH:mm:ss.SSSz

其次,需要使用@JsonFormat来指定日期格式。

jackson-databind 包中定义的@JsonFormat 让您可以更好地控制如何根据 SimpleDateFormat 格式化日期和日历值。

通过使用它,POJO MyClass 看起来像这样:

@Data
public class MyClass {
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSz", timezone = "UTC")
  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
  private LocalDateTime date;
}

现在,如果您尝试反序列化使用:

ObjectMapper mapper = new ObjectMapper();
MyClass clazz = mapper.readValue(new File("MyFile.json"), MyClass.class);
System.out.println(myClass);

然后该过程将通过,产生如下结果:

MyClass{date=2017-01-01T00:00:59.000}

【讨论】:

  • 是的,此配置有效。以下两行足以反序列化此 json 日期:@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSz") @JsonDeserialize(using = LocalDateTimeDeserializer.class) 但我们丢失了区域。
  • 您能否详细说明丢失区域是什么意思?
【解决方案2】:

您的日期格式不正确(仅附加了 UTC 作为文本),但您可以通过自定义格式化程序解决它。

public class Test {

  public static void main(String[] args) throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    MyClass localDateTime = objectMapper.readValue("{\"date\":\"2017-01-01T00:00:59.000UTC\"}", MyClass.class);
    System.out.println(localDateTime.date);
  }

  @Data
  public static class MyClass {
    @JsonDeserialize(using = CustomDeserializer.class)
    private LocalDateTime date;

  }

  public static class CustomDeserializer extends LocalDateTimeDeserializer {

    public CustomDeserializer() {
      super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }

    protected CustomDeserializer(LocalDateTimeDeserializer base, Boolean leniency) {
      super(base, leniency);
    }

    @Override
    public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
      String substring = jsonParser.getText().substring(0, jsonParser.getText().indexOf("U"));
      return LocalDateTime.parse(substring, _formatter);
    }
  }

}

【讨论】:

  • UTC 是一个区域。它不是简单的附加
  • 这个例子也可以,但是我们又丢了一个区域
【解决方案3】:

尝试删除@JsonDeserialize。 (在任何情况下,您都试图将您的日期反序列化为 LocalDateTime 但它具有时区信息,您需要尝试 ZonedDateTime 或 OffsetDateTime)。并换行

@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")

这里是为您提供完整答案的问题的链接:Spring Data JPA - ZonedDateTime format for json serialization

【讨论】:

  • 对于ZonedDateTimeOffsetDateTime 不起作用会引发以下错误:com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.ZonedDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2017-01-01T00:00:59.000UTC') 因为需要反序列化器类。并且没有为这些类型的日期类提供默认的反序列化器类。
  • 尝试将掩码中的“Z”更改为“O”。所以你的面具是“yyyy-MM-dd'T'HH:mm:ss.SSSO”。请参阅 Javadoc 了解 DateTimeFormatter 类
猜你喜欢
  • 2022-01-24
  • 1970-01-01
  • 2020-07-17
  • 1970-01-01
  • 2011-11-23
  • 2022-07-25
  • 1970-01-01
  • 2012-09-26
  • 1970-01-01
相关资源
最近更新 更多