坑啊,jackson和fastjson序列化LocalDateTime时毫秒值会丢失!

1,322 阅读2分钟

问题出现:

你们猜这个对象json序列化之后是什么?

LocalDateTime localDateTime=LocalDateTime.parse("2022-11-09 11:11:11.000", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));

是这个:2022-11-09 11:11:11.000?

这个:2022-11-09T11:11:11.000?

都不是!

是:2022-11-09T11:11:11

那我们去掉中间的T进行解析的化会怎么样呢?
LocalDateTime.parse("2022-11-09 11:11:11",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));

直接报错

Exception in thread "main" java.time.format.DateTimeParseException: Text '2022-11-09 11:11:11' could not be parsed at index 19 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) at java.time.LocalDateTime.parse(LocalDateTime.java:492)

这就比较尴尬了,这个错误藏得很深,只有在毫秒值为0时才会出现,测试大概率都不能测试到,我也是业务跑了很长时间才出现了一次。(想嘲讽的人先看后面题外话)

一些源码

jackson
g.writeNumber(value.getYear());
g.writeNumber(value.getMonthValue());
g.writeNumber(value.getDayOfMonth());
g.writeNumber(value.getHour());
g.writeNumber(value.getMinute());
int secs = value.getSecond();
int nanos = value.getNano();
if (secs > 0 || nanos > 0) {
    g.writeNumber(secs);
    if (nanos > 0) {
        if (this.useNanoseconds(provider)) {
            g.writeNumber(nanos);
        } else {
            g.writeNumber(value.get(ChronoField.MILLI_OF_SECOND));
        }
    }
}
fastjson
if (format == null) {
    if ((features & mask) != 0 || serializer.isEnabled(SerializerFeature.UseISO8601DateFormat)) {
        format = formatter_iso8601_pattern;
    } else {
        int nano = dateTime.getNano();
        if (nano == 0) {
            format = formatter_iso8601_pattern;
        } else if (nano % 1000000 == 0) {
            format = formatter_iso8601_pattern_23;
        } else {
            format = formatter_iso8601_pattern_29;
        }
    }
}
private final static String formatter_iso8601_pattern     = "yyyy-MM-dd'T'HH:mm:ss";

解决方案:

jackson
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")

fastjson

@JSONField(format = "yyyy-MM-dd'T'HH:mm:ss.SSS")

题外话

有些朋友肯定要说,你反序列化不用json框架(jackson、fastjson),自己在那儿乱写,活该你出错,我想说你说的很对,但是我们接口返回之后,对方怎么使用有时候不是我们可以控制的,对方就用String接收然后自己解析也是人家的自由,出问题肯定是找我们的,谁让我们自己缺失了毫秒值呢?