如何在 Jackson 中将 Date 序列化为 LocalDate?
How to serialize a Date as LocalDate in Jackson?
我有一个 class 字段类型 LocalDate
:
public class MyClass {
private LocalDate myDate;
}
我必须将值存储为 yyyy-MM-dd 而不是 [yyyy, M, d]
这可以通过创建 LocalDateSerializer 来完成,如 (DateTimeFormatter.ISO_LOCAL_DATE)
中所示
在我的场景中,有多个接收数据的来源。其中之一将日期发送为
ISO_INSTANT '2011-12-03T10:15:30Z'。 LocalDateDeserializer:
public class LocalDateDeserializer extends StdDeserializer<LocalDate> {
private static final long serialVersionUID = 1L;
protected LocalDateDeserializer() {
super(LocalDate.class);
}
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
return LocalDate.parse(jp.readValueAs(String.class));
}
}
抛出以下警告:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Text '2021-02-25T00:52:00.000Z' could not be parsed, unparsed text found at index 10; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Text '2021-02-25T00:52:00.000Z' could not be parsed, unparsed text found at index 10 (through reference chain: MyClass["myDate"])]
我的理解是收到的字符串无法解析为 LocalDate
: LocalDate.parse(jp.readValueAs(String.class));
让 LocalDateDeserializer 接受任何有效日期格式但返回 LocalDate
的最佳方法是什么
对于我的特定情况,我知道只有两种格式可以输入日期。我可以检查它是哪种格式并相应地进行处理。
我发布的是在我的场景中有效的方法,但我确信还有更多“稳健”的解决方案。
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String input_date = jp.readValueAs(String.class);
boolean is_date_time = input_date.contains("T");
if (is_date_time) {
int end = input_date.indexOf('T');
input_date = input_date.substring(0, end);
}
return LocalDate.parse(input_date);
}
如果您只需要在填充 MyClass
实例时将 Date
对象的日期转换为 LocalDate
,则:
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
java.util.Date
代表时间线上的一个瞬间,而不是“日期”。
但在 java 9 中,您可以执行类似的操作:
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
无需在反序列化器中进行转换,您可以在将值设置为 MyClass
实例之前在映射器方法本身中处理它,因为您有多个来源使用了多种日期时间格式。否则,您将不得不处理反序列化程序中的条件,以处理您将要接收日期的不同格式。如果您在实际将数据设置为实体 的映射器方法中处理它(考虑到您有一个 DTO class),您可以为不同的日期提供具体的实现来自不同来源的格式。
如果您仍想使用反序列化器,请为不同的日期格式使用 DateTimeFormatter
并相应地进行设置:
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MMM-dd");
if (**somecondition**) {
dtf = DateTimeFormatter.ofPattern("yyyy-MMM-dd");
}
LocalDate dt = dtf.parseLocalDate(yourinput);
return dt;
}
格式的可选部分
您可以在格式模式字符串中使用可选部分。这包含在方括号中,表示在解析过程中可能存在或不存在的日期时间字符串的一部分。像这样:
private static final DateTimeFormatter inputFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd['T'HH:mm:ssX]");
如果您确定附加不相关的时间和偏移量(Z
是 UTC 偏移量)没有更改日期,您现在可以这样解析:
for (String inputString
: new String[] { "2011-12-03T10:15:30Z", "2013-11-21" }) {
LocalDate date = LocalDate.parse(inputString, inputFormatter);
System.out.format("%-20s parsed to %s%n", inputString, date);
}
输出:
2011-12-03T10:15:30Z parsed to 2011-12-03
2013-11-21 parsed to 2013-11-21
我有一个 class 字段类型 LocalDate
:
public class MyClass {
private LocalDate myDate;
}
我必须将值存储为 yyyy-MM-dd 而不是 [yyyy, M, d]
这可以通过创建 LocalDateSerializer 来完成,如
在我的场景中,有多个接收数据的来源。其中之一将日期发送为 ISO_INSTANT '2011-12-03T10:15:30Z'。 LocalDateDeserializer:
public class LocalDateDeserializer extends StdDeserializer<LocalDate> {
private static final long serialVersionUID = 1L;
protected LocalDateDeserializer() {
super(LocalDate.class);
}
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
return LocalDate.parse(jp.readValueAs(String.class));
}
}
抛出以下警告:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Text '2021-02-25T00:52:00.000Z' could not be parsed, unparsed text found at index 10; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Text '2021-02-25T00:52:00.000Z' could not be parsed, unparsed text found at index 10 (through reference chain: MyClass["myDate"])]
我的理解是收到的字符串无法解析为 LocalDate
: LocalDate.parse(jp.readValueAs(String.class));
让 LocalDateDeserializer 接受任何有效日期格式但返回 LocalDate
对于我的特定情况,我知道只有两种格式可以输入日期。我可以检查它是哪种格式并相应地进行处理。
我发布的是在我的场景中有效的方法,但我确信还有更多“稳健”的解决方案。
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String input_date = jp.readValueAs(String.class);
boolean is_date_time = input_date.contains("T");
if (is_date_time) {
int end = input_date.indexOf('T');
input_date = input_date.substring(0, end);
}
return LocalDate.parse(input_date);
}
如果您只需要在填充 MyClass
实例时将 Date
对象的日期转换为 LocalDate
,则:
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
java.util.Date
代表时间线上的一个瞬间,而不是“日期”。
但在 java 9 中,您可以执行类似的操作:
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
无需在反序列化器中进行转换,您可以在将值设置为 MyClass
实例之前在映射器方法本身中处理它,因为您有多个来源使用了多种日期时间格式。否则,您将不得不处理反序列化程序中的条件,以处理您将要接收日期的不同格式。如果您在实际将数据设置为实体 的映射器方法中处理它(考虑到您有一个 DTO class),您可以为不同的日期提供具体的实现来自不同来源的格式。
如果您仍想使用反序列化器,请为不同的日期格式使用 DateTimeFormatter
并相应地进行设置:
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MMM-dd");
if (**somecondition**) {
dtf = DateTimeFormatter.ofPattern("yyyy-MMM-dd");
}
LocalDate dt = dtf.parseLocalDate(yourinput);
return dt;
}
格式的可选部分
您可以在格式模式字符串中使用可选部分。这包含在方括号中,表示在解析过程中可能存在或不存在的日期时间字符串的一部分。像这样:
private static final DateTimeFormatter inputFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd['T'HH:mm:ssX]");
如果您确定附加不相关的时间和偏移量(Z
是 UTC 偏移量)没有更改日期,您现在可以这样解析:
for (String inputString
: new String[] { "2011-12-03T10:15:30Z", "2013-11-21" }) {
LocalDate date = LocalDate.parse(inputString, inputFormatter);
System.out.format("%-20s parsed to %s%n", inputString, date);
}
输出:
2011-12-03T10:15:30Z parsed to 2011-12-03 2013-11-21 parsed to 2013-11-21