fasterxml日期反序列化,支持若干格式

工作中,经常对接外部接口,各个系统日期格式不是很统一,经常报出以下错误

Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2021-07-20T11:27:31Z": not a valid representation (error: Failed to parse Date value '2021-07-20T11:27:31Z': Unparseable date: "2021-07-20T11:27:31Z")
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 9] (through reference chain: com.mfhcd.saas.industry.agency.app.controller.Bean["time"])
	at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1991)
	at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:1219)

解决方案

针对以上问题问题,编写如下代码

import cn.hutool.core.date.DateException;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;


/**
 * 处理应对不同的日期格式
 * <p>
 * 支持日期格式
 * <li>yyyy-MM-dd HH:mm:ss</li>
 * <li>yyyy/MM/dd HH:mm:ss</li>
 * <li>yyyy.MM.dd HH:mm:ss</li>
 * <li>yyyy年MM月dd日 HH时mm分ss秒</li>
 * <li>yyyy-MM-dd</li>
 * <li>yyyy/MM/dd</li>
 * <li>yyyy.MM.dd</li>
 * <li>HH:mm:ss</li>
 * <li>HH时mm分ss秒</li>
 * <li>yyyy-MM-dd HH:mm</li>
 * <li>yyyy-MM-dd HH:mm:ss.SSS</li>
 * <li>yyyy-MM-dd HH:mm:ss.SSSSSS</li>
 * <li>yyyyMMddHHmmss</li>
 * <li>yyyyMMddHHmmssSSS</li>
 * <li>yyyyMMdd</li>
 * <li>EEE, dd MMM yyyy HH:mm:ss z</li>
 * <li>EEE MMM dd HH:mm:ss zzz yyyy</li>
 * <li>yyyy-MM-dd'T'HH:mm:ss'Z'</li>
 * <li>yyyy-MM-dd'T'HH:mm:ss.SSS'Z'</li>
 * <li>yyyy-MM-dd'T'HH:mm:ssZ</li>
 * <li>yyyy-MM-dd'T'HH:mm:ss.SSSZ</li>
 * <li>时间戳</li>
 *
 * @author 丁乾文
 * @date 2022/6/9 20:17
 * @since 1.0.0
 */
public class DateJsonDeserialize {


    /**
     * convert
     *
     * @param text 时间戳 or yyyy-MM-dd HH:mm:ss等
     * @return date
     */
    private static DateTime convert(String text) {
        DateTime date;
        try {
            // 支持若干日期格式,例如{yyyy-MM-dd HH:mm:ss,yyyy-MM-dd}
            date = DateUtil.parse(text);
        } catch (DateException e) {
            // 时间戳,例如{1658214991175}
            if (NumberUtil.isNumber(text)) {
                long timestamp = Long.parseLong(text);
                date = new DateTime(timestamp);
            } else {
                // 不支持的格式
                throw e;
            }
        }
        return date;
    }

    /**
     * LocalDate
     * <p>
     * 属性上增加:@JsonDeserialize(using = LocalDateJsonDeserialize.class)
     *
     * @see DateUtil#parse(java.lang.CharSequence)
     */
    public static class LocalDateType extends JsonDeserializer<LocalDate> {

        @Override
        public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            if (jsonParser != null && StrUtil.isNotBlank(jsonParser.getText())) {
                DateTime dateTime = DateJsonDeserialize.convert(jsonParser.getText());
                return LocalDateTimeUtil.of(dateTime).toLocalDate();
            } else {
                return null;
            }
        }

    }

    /**
     * LocalDateTime
     * <p>
     * 属性上增加:@JsonDeserialize(using = LocalDateTimeJsonDeserialize.class)
     *
     * @see DateUtil#parse(java.lang.CharSequence)
     */
    public static class LocalDateTimeType extends JsonDeserializer<LocalDateTime> {

        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            if (jsonParser != null && StrUtil.isNotBlank(jsonParser.getText())) {
                DateTime dateTime = DateJsonDeserialize.convert(jsonParser.getText());
                return LocalDateTimeUtil.of(dateTime);
            } else {
                return null;
            }
        }

    }

    /**
     * Date
     * <p>
     * 属性上增加:@JsonDeserialize(using = DateJsonDeserialize.class)
     *
     * @see DateUtil#parse(java.lang.CharSequence)
     */
    public static class DateType extends JsonDeserializer<Date> {

        @Override
        public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            if (jsonParser != null && StrUtil.isNotBlank(jsonParser.getText())) {
                return DateJsonDeserialize.convert(jsonParser.getText());
            } else {
                return null;
            }
        }

    }

}

测试代码

编写如下代码进行简单测试

@RestController
public class TestController {

    @PostMapping("test")
    public Boolean test(@RequestBody Bean bean) {
        System.out.println(bean.getTime1());
        System.out.println(bean.getTime2());
        System.out.println(bean.getTime3());
        return true;
    }

}

@Data
class Bean {

    @JsonDeserialize(using = DateJsonDeserialize.DateType.class)
    private Date time1;

    @JsonDeserialize(using = DateJsonDeserialize.LocalDateType.class)
    private LocalDate time2;

    @JsonDeserialize(using = DateJsonDeserialize.LocalDateTimeType.class)
    private LocalDateTime time3;

}

请求接口参数如下

{
	"time1": "2021-07-20T11:27:31Z",
	"time2": "2021/07/20 11:27:31",
	"time3": "1658214991175"
}

控制台打印如下日志

2021-07-20 11:27:31
2021-07-20
2022-07-19T15:16:31.175
更新日期:
作者: qwding