如何在 @JsonFormat 中为 Jackson 的时间戳解析设置毫秒可选?
How to make milliseconds optional in @JsonFormat for Timestamp parsing with Jackson?
我的对象中有以下声明:
@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")
对于那些无法使 [.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;
}
}
如果毫秒由 1 位或 2 位或 3 位数字组成,您可以使用此模式
JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS][.SS][.S]X")
可选部分顺序严格
我的对象中有以下声明:
@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")
对于那些无法使 [.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;
}
}
如果毫秒由 1 位或 2 位或 3 位数字组成,您可以使用此模式
JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS][.SS][.S]X")
可选部分顺序严格