fastjson2 JSON反序列化时校验LocalDateTime类型数据

背景: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

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值