如何在 @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")

可选部分顺序严格