您必须告诉杰克逊日期是什么格式。基本上,您
year-month-day紧接着是
hour:minute:second.microseconds和带有2个数字的偏移量(
+02)。因此,您的模式将是:
@JsonProperty("timestamp")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSSx")private OffsetDateTime timestamp;查看所有日期/时间模式以获得更详细的说明。
如果要在中保留相同的offset(
+02)
OffsetDateTime,请不要忘记将
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE选项调整为
false。
如果将此选项设置为
true(在我的测试中),结果将转换为UTC(但实际上将转换为Jackson中配置的任何时区):
2017-09-17T11:45:42.710576Z
如果将设置为
false,则会保留输入中使用的偏移量:
2017-09-17T13:45:42.710576 + 02:00
上面的代码仅在小数点后6位有效。但是,如果此数量有所变化,则可以使用以分隔的可选模式
[]。
示例:如果输入可以有6或3个十进制数字,则可以使用
pattern = "yyyy-MM-ddHH:mm:ss.[SSSSSS][SSS]x"。可选部分,
[SSSSSS]并
[SSS]告诉解析器考虑6位或3位数字。
可选模式的问题在于,在序列化时,它会打印所有模式(因此它将打印秒的小数两次:6位 和 3位)。
另一种选择是创建自定义的序列化器和反序列化器(通过扩展
com.fasterxml.jackson.databind.JsonSerializer和
com.fasterxml.jackson.databind.JsonDeserializer):
public class CustomDeserializer extends JsonDeserializer<OffsetDateTime> { private DateTimeFormatter formatter; public CustomDeserializer(DateTimeFormatter formatter) { this.formatter = formatter; } @Override public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { return OffsetDateTime.parse(parser.getText(), this.formatter); }}public class CustomSerializer extends JsonSerializer<OffsetDateTime> { private DateTimeFormatter formatter; public CustomSerializer(DateTimeFormatter formatter) { this.formatter = formatter; } @Override public void serialize(OffsetDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException { gen.writeString(value.format(this.formatter)); }}然后,您可以在中注册
JavaTimeModule。如何配置它取决于您所使用的环境(例如:在Spring中,您可以在xml文件中进行配置)。我将以编程方式作为示例。
首先,我使用来创建格式化程序
java.time.format.DateTimeFormatterBuilder:
DateTimeFormatter formatter = new DateTimeFormatterBuilder() // date/time .appendPattern("yyyy-MM-dd HH:mm:ss") // optional fraction of seconds (from 0 to 9 digits) .optionalStart().appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true).optionalEnd() // offset .appendPattern("x") // create formatter .toFormatter();此格式化程序接受0到9位数字的可选秒数。然后,我使用上面的自定义类并在中注册它们
ObjectMapper:
// set formatter in the module and register in object mapperObjectMapper mapper = new ObjectMapper();mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);JavaTimeModule module = new JavaTimeModule();module.addSerializer(OffsetDateTime.class, new CustomSerializer(formatter));module.addDeserializer(OffsetDateTime.class, new CustomDeserializer(formatter));mapper.registerModule(module);
我还
@JsonFormat从字段中删除了注释:
@JsonProperty("timestamp")private OffsetDateTime timestamp;现在,它接受的值
2017-09-17 13:45:42+02(不包括秒)和
2017-09-1713:45:42.71014+02(5个十进制数字)。它可以解析0到9个十进制数字(9是API支持的最大值),并且在序列化时打印完全相同的数量。
上面的替代方法非常灵活,因为它允许在自定义类中设置格式化程序。但是,它还会为所有
OffsetDateTime字段设置序列化和反序列化。
如果您不想这样做,还可以使用固定的格式化程序创建一个类:
static class CustomDeserializer extends JsonDeserializer<OffsetDateTime> { private DateTimeFormatter formatter = // create formatter as above // deserialize method is the same}static class CustomSerializer extends JsonSerializer<OffsetDateTime> { private DateTimeFormatter formatter = // create formatter as above // serialize method is the same}然后,您可以使用注释
com.fasterxml.jackson.databind.annotation.JsonSerialize和将这些仅添加到所需的字段中
com.fasterxml.jackson.databind.annotation.JsonDeserialize:
@JsonProperty("timestamp")@JsonSerialize(using = CustomSerializer.class)@JsonDeserialize(using = CustomDeserializer.class)private OffsetDateTime timestamp;这样,您无需在模块中注册自定义序列化程序,只有注释字段将使用自定义类(其他
OffsetDateTime字段将使用默认设置)。



