记录一次fastjson吃了我的null值| Java Debug 笔记

610 阅读1分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

示例回显代码

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>(16);
        map.put("test1", null);
        map.put("test2", null);
        map.put("test3", "test3");
        map.put("test4", "test4");
        map.put("test5", "test5");
        Object obj = JSON.toJSON(map);
        System.out.println(obj);
    }

输出

{"test4":"test4","test5":"test5","test3":"test3"}

发现jsonnull的已经没了,这个时候去网络进行搜索其实可以直接找到答案,但是还是调试一下为好

  • 一来锻炼寻错思路
  • 二来熟悉fastjson源码

调试

我们先把断点放到15行,方便我们观察是toJSON干掉了null还是打印的时候干掉的

image.png

如图很清晰,obj对象中是全量 map 对象
然后我们使用,F7 就是Step into 进入 toString() 方法
因为运行时多态,调用子类方法,这里调用的是JSON.class中的 toString()方法
如下:

    public String toString() {
        return this.toJSONString();
    }

然后继续使用 Step into 步入 toJSONString() 方法

image.png

如图,我们找到了最重要的一步,结束调试(使用F9

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>(16);
        map.put("test1", null);
        map.put("test2", null);
        map.put("test3", "test3");
        map.put("test4", "test4");
        map.put("test5", "test5");
        Object obj = JSON.toJSON(map);
        SerializeWriter out = new SerializeWriter();
        JSONSerializer jsonSerializer = new JSONSerializer(out);
        jsonSerializer.write(obj);// 断点
        System.out.println(obj);
    }

image.png

步入MapSerializerwrite 方法

image.png

最关键的地方找到了, 就是配置SerializerFeature.WriteMapNullValue

查看方法头部

public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

猜测要么是在SerializeWriter中要么是在SerializeWriter中要配置SerializerFeature.WriteMapNullValue

image.png

这个时候发现如下代码也可以配置

jsonSerializer.config(SerializerFeature.WriteMapNullValue, true);

查看 config 方法源码

    public void config(SerializerFeature feature, boolean state) {
        this.out.config(feature, state);
    }

调用的还是SerializeWriter 中的

我们也可以使用JSON.toJSONString去直接打印,发现构造方法中也有可以配置的地方

image.png

最终代码

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>(16);
        map.put("test1", null);
        map.put("test2", null);
        map.put("test3", "test3");
        map.put("test4", "test4");
        map.put("test5", "test5");
        Object obj = JSON.toJSON(map);


        SerializeWriter out = new SerializeWriter();
//        out.config(SerializerFeature.WriteMapNullValue, true);
        JSONSerializer jsonSerializer = new JSONSerializer(out);
        jsonSerializer.config(SerializerFeature.WriteMapNullValue, true);
        jsonSerializer.write(obj);
        
        // 1 和 2 任选其一
        System.out.println(out);// 1
        System.out.println(JSON.toJSONString(obj,SerializerFeature.WriteMapNullValue)); // 2
        
    }

tips:有人说为啥不直接查看文档,诶,我可以查文档,可我就不,我就是要调试,就是玩,我命由我不由天