如何在 @JsonFormat 中使毫秒可选,以便使用 Jackson 进行时间戳解析?

问题描述 投票:0回答:4

我的对象中有以下声明:

@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 json jackson deserialization iso8601
4个回答
19
投票

如果您使用的是 Java 8,请尝试在方括号内指定

.SSS
[.SSS]

JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS]X")

14
投票

如果 millis 由 1 或 2 或 3 位数字组成,您可以使用此模式

JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS][.SS][.S]X")

可选部分顺序严格


4
投票

对于那些无法让

[.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;
    }
}

0
投票

是否可以用方括号指定可选格式组件取决于所使用的反序列化器。 SimpleDateFormat 无法识别它。但是如果你在fasterxml中注册jsr310模块(可能通过JavaTimeModule)并反序列化java.time类,那么这是可能的。

如何?它使用 DateTimeFormatter ,其中包含以下文档:

   [       optional section start
   ]       optional section end
© www.soinside.com 2019 - 2024. All rights reserved.