杰克逊 - 无法使用时区偏移'在索引23处找到未分析的文本反序列化日期时间'

时间:2017-07-04 20:25:09

标签: java spring datetime jackson datetime-parsing

我的日期时间必须来自前端,时区偏移:2017-07-04T06:00:00.000+01:00

我无法用杰克逊对其进行反序列化。 错误是:

  

文字'2017-07-04T06:00:00.000 + 01:00'无法解析,未解析   在索引23处找到的文字;

我试图谷歌所有人的解决方案都是关于最后的Z的DateTime。

    @NotNull
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS aZ")
    private LocalDateTime time;

有没有解决方案?

1 个答案:

答案 0 :(得分:4)

pattern a is used to parse AM/PM,它不在输入String中,这就是你得到解析错误的原因。

输入格式匹配OffsetDateTime,可以使用相应的built-in formatter DateTimeFormatter.ISO_OFFSET_DATE_TIME进行解析,因此您可以在反序列化器对象中使用此格式化程序并在模块中注册它。您还必须从字段中删除JsonFormat注释。

ObjectMapper om = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
LocalDateTimeDeserializer deserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
module.addDeserializer(LocalDateTime.class, deserializer);
om.registerModule(module);

这将解析输入并将其转换为LocalDateTime。在我做过的测试中,LocalDateTime的值设置为2017-07-04T06:00

要控制输出,您可以执行以下操作:

om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

哪个会将LocalDateTime输出为2017-07-04T06:00:00,或者您可以使用自定义格式化程序:

LocalDateTimeSerializer serializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS a"));
module.addSerializer(LocalDateTime.class, serializer);

上面的序列化程序会将字段输出为2017-07-04T06:00:00.000 AM。请注意,Z模式不起作用,因为LocalDateTime没有时区信息且无法解析其偏移量 - 因为当您反序列化为LocalDateTime时,输入(+01:00)丢失了。

另一种替代方法(无需配置对象映射器)是在注释中使用正确的模式:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS[xxx]")
private LocalDateTime time;

请注意,我使用了模式[xxx],因为偏移量(+01:00)可以是可选的:反序列化时,由于LocalDateTime没有关于时区和偏移量的信息,此信息会丢失,因此,当序列化此字段时将无法找到 - 使字段可选(使用[]分隔符)使其适用于反序列化和序列化。

这将反序列化输入2017-07-04T06:00:00.000+01:00并序列化为2017-07-04T06:00:00.000(请注意,序列化中不使用可选偏移量,因为LocalDateTime没有此类信息。)

如果您需要不同的反序列化和序列化格式,您还可以在字段中创建自定义类并进行设置:

public class CustomDeserializer extends LocalDateTimeDeserializer {
    public CustomDeserializer() {
        super(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }
}

public class CustomSerializer extends LocalDateTimeSerializer {
    public CustomSerializer() {
        super(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS a"));
    }
}

// in this case, don't use @JsonFormat
@JsonSerialize(using = CustomSerializer.class)
@JsonDeserialize(using = CustomDeserializer.class)
private LocalDateTime time;

这将使用格式2017-07-04T06:00:00.000+01:00进行反序列化,使用格式2017-07-04T06:00:00.000 AM进行序列化。