我的对象中有以下声明:
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX")
private ZonedDateTime start;
当我解析像 2016-12-08T12:16:07.124Z 这样的时间戳(使用 Jackson Json De-serilaizer)时,它工作正常,但是一旦我收到时间戳没有毫秒(例如“2016-12-08T12:16: 07Z"),它会抛出异常。
如何在格式规范中使毫秒可选?
如果您使用的是 Java 8,请尝试在方括号内指定
.SSS
[.SSS]
JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS]X")
如果 millis 由 1 或 2 或 3 位数字组成,您可以使用此模式
JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS][.SS][.S]X")
可选部分顺序严格
对于那些无法让
[.SSS]
解决方案发挥作用的人,这就是我最终所做的。
保留字段上的
@JsonFormat
注释以进行序列化,但构建一个自定义反序列化器来解析可能未指定毫秒部分的日期。实现解串器后,您必须将其注册为 ObjectMapper
作为 SimpleModule
class DateDeserializer extends StdDeserializer<Date> {
private static final SimpleDateFormat withMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
private static final SimpleDateFormat withoutMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
public DateDeserializer() {
this(null);
}
public DateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String dateString = p.getText();
if (dateString.isEmpty()) {
//handle empty strings however you want,
//but I am setting the Date objects null
return null;
}
try {
return withMillis.parse(dateString);
} catch (ParseException e) {
try {
return withoutMillis.parse(dateString);
} catch (ParseException e1) {
throw new RuntimeException("Unable to parse date", e1);
}
}
}
}
现在您已经有了一个自定义解串器,剩下的就是注册它。我正在使用我的项目中已有的
ContextResolver<ObjectMapper>
来执行此操作,但是无论您如何使用 ObjectMapper
都应该没问题。
@Provider
class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperContextResolver() {
mapper = new ObjectMapper();
SimpleModule dateModule = new SimpleModule();
dateModule.addDeserializer(Date.class, new DateDeserializer());
mapper.registerModule(dateModule);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
是否可以用方括号指定可选格式组件取决于所使用的反序列化器。 SimpleDateFormat 无法识别它。但是如果你在fasterxml中注册jsr310模块(可能通过JavaTimeModule)并反序列化java.time类,那么这是可能的。
如何?它使用 DateTimeFormatter ,其中包含以下文档:
[ optional section start
] optional section end