Java避坑指南:记一次FastJson带来的BUG

2,424 阅读3分钟

这是我参与更文挑战的第1天,活动详情查看: 更文挑战

喵君镇楼,小编第一次在掘金写文章,文笔不好各位大佬们海涵

业务场景:

上游服务将业务对象转化为JSON通过mq消息推送至到下游服务消费;

出现问题:

最近在写代码的时候遇到问题,通过JSON.toJSONString方法将一个实体对象转为json字符串,转出来发现原本 对象中value为null的字段被过滤掉了。。。下游服务在接受到mq的消息后进行消费 JSON转对象时 发现部分字段丢失导致JSON转化异常

net.sf.json.JSONException:java.lang.reflect.InvocationTargetException

具体业务代码就不粘了给大家写一个小的demo列举一下:

@Test
    public void test(){
        user user = new user();
        user.setName("张三");
        user.setSchool("武汉大学");
        String jsonString = JSON.toJSONString(user);
        System.out.println("对象 -》JSON "+jsonString);
    }

    
    @Data
    class user{
        private String name;
        private String age;
        private String school;
    }

如上代码,当User对象中的age字段为空的时候,这个时候转换为json

图片.png

我们可以看到转换为JSON后age字段丢失了,这样就会导致当我们用对象接收不了或者转为对象的时候可能会导致json转换异常,或者我们有时候会有当这个字段为空的时候可以将这个字段展示出来 或者给一个默认值;

解决方案:

查看JSON.toJSONString()源码:

图片.png 如上,可以发现toJSONString() 有多个重载方法 这里我们就需要给toJSONString方法配置SerializerFeature属性

SerializerFeature属性的枚举类如下:

说明
QuoteFieldNames输出key时是否使用双引号,默认为true
WriteMapNullValue是否输出值为null的字段,默认为false
WriteNullNumberAsZero数值字段如果为null,输出为0,而非null
WriteNullListAsEmptyList字段如果为null,输出为[],而非null
WriteNullStringAsEmpty字符类型字段如果为null,输出为"",而非null
WriteNullBooleanAsFalseBoolean字段如果为null,输出为false,而非null

修改代码后:

@Test
    public void test(){
        user user = new user();
        user.setName("张三");
        user.setSchool("武汉大学");
        String jsonString = JSON.toJSONString(user, SerializerFeature.WriteNullStringAsEmpty);
        System.out.println("对象 -》JSON "+jsonString);
    }


    @Data
    class user{
        private String name;
        private String age;
        private String school;
    }
}

输出为:

图片.png ok了!解决问题,当然toJSONString方法还有很多扩展,比如我们想要为空的时候输出一个特定的字符,这个时候就需要用到过滤器了,仔细看看JSON.toJSONString的其他几个方法

图片.png JSON.toJSONString有很多过滤器 具体就不类聚了 大家感兴趣的可以自己去看一下源码,这里仅展示一个例子:

@Test
    public void test(){
        user user = new user();
        user.setName("张三");
        user.setSchool("武汉大学");
        String jsonString = JSON.toJSONString(user, SerializerFeature.WriteNullStringAsEmpty);
        System.out.println(JSON.toJSONString(user, (ValueFilter) (name, age, school) -> {
            if(age == null){
                return "18";
            }

            return age;
        }));
        System.out.println("对象 -》JSON "+jsonString);
    }


    @Data
    class user{
        private String name;
        private String age;
        private String school;
    }

这样就OK啦!

你当这样就完了吗?阿芙卡丝闹特!!!

当然他还有一个比较强大的地方就是PropertyFilter 比如我们有的值为null需要过滤,有的又不需要过滤这个时候Filter就来了

@Test
    public void test(){
        user user = new user();
        user.setName("张三");
        user.setSchool("武汉大学");
        String jsonString = JSON.toJSONString(user, SerializerFeature.WriteNullStringAsEmpty);
        System.out.println(JSON.toJSONString(user, (ValueFilter) (name, age, school) -> {
            if(age == null){
                return "18";
            }

            return age;
        }));

        System.out.println(JSON.toJSONString(user, new PropertyFilter() {
            @Override
            public boolean apply(Object object, String name, Object value) {
                return name.equals("张三") || value != null;
            }
        }, SerializerFeature.WriteMapNullValue));
    }
        System.out.println("对象 -》JSON "+jsonString);
    }


    @Data
    class user{
        private String name;
        private String age;
        private String school;
    }

ok!文章到此就结束了,希望可以对大家有帮助,第一次写作文笔不太好,小编会慢慢进行改善,有不对的地方希望大家可以提出来的,一起成长;

整洁成就卓越代码,细节之中只有天地