用Jackson反序列化LocalDateTime

时间:2017-12-22 17:17:40

标签: java date jackson

我尝试反序列化此属性时出错:

@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime deliveryDate;

这是反序列化类:

public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

    @Override
    public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {

        if (parser.getCurrentToken().equals(JsonToken.VALUE_STRING)) {
            String rawDate = parser.getText();
            return LocalDateTime.parse(rawDate);
        } else {
            throw context.wrongTokenException(parser, JsonToken.VALUE_STRING, "Expected string.");
    }
}

序列化类:

public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {

        gen.writeString(value.toString());
    }

这是我得到的错误:

"timestamp":1513962011642,"status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Could not read document: Text '2017-12-22T16:00:00.874Z' could not be parsed, unparsed text found at index 23 

你知道为什么吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

TL;博士

Instant而不是LocalDateTime处理。

Instant.parse( "2017-12-22T16:00:00.874Z" )

详细

不确定JSON的原始数据。如果您的输入数据为1513962011642,那么它似乎是一个自纪元以来的计数,大概是1970-01-01T00:00:00Z的epoch reference date,即UTC中1970年的第一个时刻。

Instant instant = Instant.ofEpochMilli( 1_513_962_011_642L ) ;

如果原始输入为2017-12-22T16:00:00.874Z,则直接解析为Instant。该字符串采用标准ISO 8601格式。最后ZZulu的缩写,表示UTC。

在解析/生成字符串时,java.time类默认使用标准格式。

Instant instant = Instant.parse( "2017-12-22T16:00:00.874Z" ) ;

LocalDateTime故意缺少time zoneoffset from UTC的概念,因此代表实际时刻,而不是时间轴上的一个点。您错误地试图将您的值放入错误的类中,因为它无法表示UTC值。

相反,将该输入作为Instant对象处理。即时代表UTC中时间轴上的一个点,其分辨率为nanoseconds

答案 1 :(得分:0)

实际上错误非常简单,它表示spring不能将此字符串"2017-12-22T16:00:00.874Z"反序列化为LocalDateTime。 如果您将运行下一个代码,您将看到相同的错误:

public static void main(String[] args) {
    System.out.println(LocalDateTime.parse("2017-12-22T16:00:00.874Z"));
}

错误的来源是索引23处的字符'Z'。如果您要删除此字符,则上述代码将起作用。因此,我建议您检查字符串中存在此'Z'字符的原因,而序列化程序不会添加它。