背景:fastjson2在处理时间日期格式时,输入非法的日期字符串字符串,转成Date、LocalDateTime等类型时,有时候不会报错,为处理这样的情况,需要增加反序列化处理。
本文使用的fastjson2版本依赖
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.49</version>
</dependency>
一、测试转换成Date类型
@Data
class A {
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date key1;
}
@Test
public void test(){
String json1 = "{\"key1\": \"1\"}";
// 无异常,时间格式不符合 不符合预期 结果:A(key1=Thu Jan 01 08:00:00 CST 1970)
System.out.println(JSON.parseObject(json1, A.class));
String json2 = "{\"key1\": \"2024-05-01\"}";
// 无异常,时间格式不符合 不符合预期 结果:A(key1=Wed May 01 00:00:00 CST 2024)
System.out.println(JSON.parseObject(json2, A.class));
String json3 = "{\"key1\": \"2024-05-01 66\"}";
// 这种情况下会抛出异常 java.time.format.DateTimeParseException: Text '2024-05-01 66' could not be parsed at index 10
System.out.println(JSON.parseObject(json3, A.class));
}
@JSONField(format = "日期格式")
可以用来指定期望的时间格式,但是在某些情况下不会报错。
二、测试转换成LocalDateTime类型
@Data
class A {
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime key1;
}
@Test
public void test() {
String json1 = "{\"key1\": \"1\"}";
// 无异常,时间格式不符合 不符合预期 结果:A(key1=Thu Jan 01 08:00:00 CST 1970)
System.out.println(JSON.parseObject(json1, A.class));
String json2 = "{\"key1\": \"2024-05-01\"}";
// 无异常,时间格式不符合 不符合预期 结果:A(key1=Wed May 01 00:00:00 CST 2024)
System.out.println(JSON.parseObject(json2, A.class));
String json3 = "{\"key1\": \"2024-05-01T00:00:00.222\"}";
// 无异常,时间格式不符合 不符合预期 A(key1=2024-05-01T00:00:00.222)
System.out.println(JSON.parseObject(json3, A.class));
}
可以看到@JSONField(format = "日期格式")
在解析成LocalDateTime 类型时并没有生效,查看源码中对JSONField类中format的注释:
说明该属性仅对Date生效,那怎么处理上述不会报错的情况呢?
三、自定义反序列化器
以LocalDateTime作为参考:
public class LocalDateTimeReader implements ObjectReader<LocalDateTime> {
public static final LocalDateTimeReader INSTANCE = new LocalDateTimeReader();
private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
@Override
public LocalDateTime readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
if (jsonReader.nextIfNull()) {
return null;
}
String dateTimeStr = jsonReader.readString();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
LocalDateTime validDateTime;
try {
validDateTime = LocalDateTime.parse(dateTimeStr, formatter);
} catch (Exception e) {
throw new RuntimeException(String.format("时间格式有误,请检查时间格式:%s", DATE_PATTERN));
}
return validDateTime;
}
}
四、使用自定义反序列化器
在需要校验的日期格式上加上注解:
@JSONField(deserializeUsing = LocalDateTimeReader.class)
或者全局注册(但是会影响到所有的该类型,需要慎重):
JSON.register(LocalDateTime.class, LocalDateTimeReader.INSTANCE);
五、测试
全局注册测试
@Data
class A {
private LocalDateTime key1;
}
@Test
public void test1() {
JSON.register(LocalDateTime.class, LocalDateTimeReader.INSTANCE);
String json1 = "{\"key1\": \"1\"}";
// 有异常,时间格式不符合 符合预期 结果:com.alibaba.fastjson2.JSONException... Caused by: java.lang.RuntimeException: 时间格式有误,请检查时间格式:yyyy-MM-dd HH:mm:ss
// System.out.println(JSON.parseObject(json1, A.class));
String json2 = "{\"key1\": \"2024-05-01\"}";
// 有异常,时间格式不符合 符合预期 结果:com.alibaba.fastjson2.JSONException... Caused by: java.lang.RuntimeException: 时间格式有误,请检查时间格式:yyyy-MM-dd HH:mm:ss
// System.out.println(JSON.parseObject(json2, A.class));
String json3 = "{\"key1\": \"2024-05-01T00:00:00.222\"}";
// 有异常,时间格式不符合 符合预期 结果:com.alibaba.fastjson2.JSONException... Caused by: java.lang.RuntimeException: 时间格式有误,请检查时间格式:yyyy-MM-dd HH:mm:ss
System.out.println(JSON.parseObject(json3, A.class));
}
注解测试
@Data
class A {
@JSONField(deserializeUsing = LocalDateTimeReader.class)
private LocalDateTime key1;
}
@Test
public void test2() {
String json1 = "{\"key1\": \"1\"}";
// 有异常,时间格式不符合 符合预期 结果:com.alibaba.fastjson2.JSONException... Caused by: java.lang.RuntimeException: 时间格式有误,请检查时间格式:yyyy-MM-dd HH:mm:ss
// System.out.println(JSON.parseObject(json1, A.class));
String json2 = "{\"key1\": \"2024-05-01\"}";
// 有异常,时间格式不符合 符合预期 结果:com.alibaba.fastjson2.JSONException... Caused by: java.lang.RuntimeException: 时间格式有误,请检查时间格式:yyyy-MM-dd HH:mm:ss
// System.out.println(JSON.parseObject(json2, A.class));
String json3 = "{\"key1\": \"2024-05-01T00:00:00.222\"}";
// 有异常,时间格式不符合 符合预期 结果:com.alibaba.fastjson2.JSONException... Caused by: java.lang.RuntimeException: 时间格式有误,请检查时间格式:yyyy-MM-dd HH:mm:ss
System.out.println(JSON.parseObject(json3, A.class));
}
测试完毕,都能够抛出异常
参考链接:
https://github.com/alibaba/fastjson2/wiki/register_custom_reader_writer_cn