使用 Jackson 反序列化 Java 8 LocalDateTime
Deserialize Java 8 LocalDateTime with Jackson
在 Jackson 2.11 中,序列化期间的 LocalDataTime 格式发生了变化。我有反序列化的问题。我找到了从 objectMapper 覆盖配置的解决方案,如下所示:
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper()
{
ObjectMapper mapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
mapper.registerModule(javaTimeModule);
return mapper;
}
但我仍然无法将 json 字符串反序列化为 java 模型:
@Data
public class CustomLocalDataTime {
//@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSxxx") <- not working
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") // <- not working
// @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", shape = JsonFormat.Shape.STRING) <- not working
private LocalDateTime date;
}
所以我从一些响应 localdatatime 收到格式示例:2022-04-05T05:00:00.000+00:00 并且在反序列化过程中我仍然收到错误:
com.fasterxml.jackson.databind.exc.InvalidFormatException:
Cannot deserialize value of type `java.time.LocalDateTime`
from String "2022-04-05T05:00:00.000+00:00": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2022-04-05T05:00:00.000+00:00'
could not be parsed, unparsed text found at index 23
at [Source: (String)"{"date":"2022-04-05T05:00:00.000+00:00"}"; line: 1, column: 9]
我通过重现此错误收到此错误:
@PostConstruct
public void customDeserializeTest() {
String content =
"{\"date\":\"2022-04-05T05:00:00.000+00:00\"}";
try {
CustomLocalDataTime customLocalDataTime = objectMapper.readValue(content, CustomLocalDataTime.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
我也尝试添加:com.fasterxml.jackson.databind.annotation.
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
但这也行不通。
非常感谢您的指导。
错误的数据类型
正如其他人评论的那样,您使用了错误的数据类型。
LocalDateTime
class 故意缺少任何 time zone or offset-from-UTC 的概念。所以这个class不能代表一个时刻,时间轴上的一个特定点。 class 仅表示一个日期和 time-of-day,但我们不知道该日期和 time-of-day 是用于日本东京、法国图卢兹还是美国俄亥俄州托莱多。
因此 LocalDateTime
class 不符合您的输入。
字符串输入:
2022-04-05T05:00:00.000+00:00
2022-04-05T05:00:00.000Z
…两者都代表 UTC 中的时刻,与 UTC 的偏移量为零 hours-minutes-seconds。第二个末尾的 Z
是 +00:00
的标准 ISO 8601 缩写,发音为“Zulu”。
Instant
& OffsetDateTime
您可以将此类输入解析为 Instant
个对象或更灵活的 OffsetDateTime
个对象。
这些输入字符串使用标准 ISO 8601 格式。 java.time classes 在 parsing/generating 时默认使用这些格式。因此无需指定格式模式。
Instant instant = Instant.parse( "2022-04-05T05:00:00.000+00:00" ) ;
Instant instant2 = Instant.parse( "2022-04-05T05:00:00.000Z" ) ;
OffsetDateTime odt = OffsetDateTime.parse( "2022-04-05T05:00:00.000+00:00" ) ;
OffsetDateTime odt2 = OffsetDateTime.parse( "2022-04-05T05:00:00.000Z" ) ;
看到这个 code run live at IdeOne.com。
instant: 2022-04-05T05:00:00Z
instant2: 2022-04-05T05:00:00Z
odt: 2022-04-05T05:00Z
odt2: 2022-04-05T05:00Z
一条评论使用 ZonedDateTime
提及。那将是 ill-advised。时区的名称格式为 Continent/Region
,例如 Europe/Paris
或 Pacific/Auckland
。您的输入只有偏移量,没有时区。所以 ZonedDateTime
在这里会产生误导和混淆。
偏移量只是 UTC 本初子午线之前或之后的 hours-minutes-seconds 数。时区要多得多。时区是特定地区人们使用的偏移量的过去、现在和未来变化的命名历史。
在 Jackson 2.11 中,序列化期间的 LocalDataTime 格式发生了变化。我有反序列化的问题。我找到了从 objectMapper 覆盖配置的解决方案,如下所示:
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper()
{
ObjectMapper mapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
mapper.registerModule(javaTimeModule);
return mapper;
}
但我仍然无法将 json 字符串反序列化为 java 模型:
@Data
public class CustomLocalDataTime {
//@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSxxx") <- not working
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") // <- not working
// @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", shape = JsonFormat.Shape.STRING) <- not working
private LocalDateTime date;
}
所以我从一些响应 localdatatime 收到格式示例:2022-04-05T05:00:00.000+00:00 并且在反序列化过程中我仍然收到错误:
com.fasterxml.jackson.databind.exc.InvalidFormatException:
Cannot deserialize value of type `java.time.LocalDateTime`
from String "2022-04-05T05:00:00.000+00:00": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2022-04-05T05:00:00.000+00:00'
could not be parsed, unparsed text found at index 23
at [Source: (String)"{"date":"2022-04-05T05:00:00.000+00:00"}"; line: 1, column: 9]
我通过重现此错误收到此错误:
@PostConstruct
public void customDeserializeTest() {
String content =
"{\"date\":\"2022-04-05T05:00:00.000+00:00\"}";
try {
CustomLocalDataTime customLocalDataTime = objectMapper.readValue(content, CustomLocalDataTime.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
我也尝试添加:com.fasterxml.jackson.databind.annotation.
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
但这也行不通。
非常感谢您的指导。
错误的数据类型
正如其他人评论的那样,您使用了错误的数据类型。
LocalDateTime
class 故意缺少任何 time zone or offset-from-UTC 的概念。所以这个class不能代表一个时刻,时间轴上的一个特定点。 class 仅表示一个日期和 time-of-day,但我们不知道该日期和 time-of-day 是用于日本东京、法国图卢兹还是美国俄亥俄州托莱多。
因此 LocalDateTime
class 不符合您的输入。
字符串输入:
2022-04-05T05:00:00.000+00:00
2022-04-05T05:00:00.000Z
…两者都代表 UTC 中的时刻,与 UTC 的偏移量为零 hours-minutes-seconds。第二个末尾的 Z
是 +00:00
的标准 ISO 8601 缩写,发音为“Zulu”。
Instant
& OffsetDateTime
您可以将此类输入解析为 Instant
个对象或更灵活的 OffsetDateTime
个对象。
这些输入字符串使用标准 ISO 8601 格式。 java.time classes 在 parsing/generating 时默认使用这些格式。因此无需指定格式模式。
Instant instant = Instant.parse( "2022-04-05T05:00:00.000+00:00" ) ;
Instant instant2 = Instant.parse( "2022-04-05T05:00:00.000Z" ) ;
OffsetDateTime odt = OffsetDateTime.parse( "2022-04-05T05:00:00.000+00:00" ) ;
OffsetDateTime odt2 = OffsetDateTime.parse( "2022-04-05T05:00:00.000Z" ) ;
看到这个 code run live at IdeOne.com。
instant: 2022-04-05T05:00:00Z
instant2: 2022-04-05T05:00:00Z
odt: 2022-04-05T05:00Z
odt2: 2022-04-05T05:00Z
一条评论使用 ZonedDateTime
提及。那将是 ill-advised。时区的名称格式为 Continent/Region
,例如 Europe/Paris
或 Pacific/Auckland
。您的输入只有偏移量,没有时区。所以 ZonedDateTime
在这里会产生误导和混淆。
偏移量只是 UTC 本初子午线之前或之后的 hours-minutes-seconds 数。时区要多得多。时区是特定地区人们使用的偏移量的过去、现在和未来变化的命名历史。