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

M U*_*M U 6 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;
Run Code Online (Sandbox Code Playgroud)

有什么解决办法吗?

小智 5

模式a用于解析AM / PM,它不在输入中String,这就是为什么会出现解析错误的原因。

输入格式与匹配OffsetDateTime,可以使用相应的内置格式化程序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);
Run Code Online (Sandbox Code Playgroud)

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


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

om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Run Code Online (Sandbox Code Playgroud)

它将输出LocalDateTimeas 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);
Run Code Online (Sandbox Code Playgroud)

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


另一种选择(无需配置对象映射器)是在批注中使用正确的模式:

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

请注意,我[xxx]之所以使用此模式,是因为offset(+01:00)可以是可选的:反序列化时,此信息会丢失,因为a 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;
Run Code Online (Sandbox Code Playgroud)

这将使用2017-07-04T06:00:00.000+01:002017-07-04T06:00:00.000 AM序列化格式和序列化格式。