debug下map效率问题_Gson对Map中值为null的字段转换为空字符串输出

779ebbf588257ae5e1485474b3a8d85c.gif喜欢就关注我吧,订阅更多最新消息

之前我写过一篇文章《Gson对字符串null的字段转换为空字符串输出》,有个兄弟评论说:定义返回的对象,code,msg,object data类型 data类型里面如果是List的map好像还是转不了。。

36bc77169833920a99ad95ed7d1c2035.png

上图代码的maps输出结果是:[{"id":"123"},{"id":"123"},{"id":"123"}]

看了上面的代码,不知道其他同学有什么想法?我发现还是有人没有理解原理,如果不知道为什么,这时候debug源码很快就可以获得答案。

Gson有自己适配器,所有map都会走了默认的MapTypeAdapterFactory类。在这里类里面write方法中,对value的判断调用valueTypeAdapter.write(out, entry.getValue());

@Override public void write(JsonWriter out, Map map) throws IOException {      if (map == null) {        out.nullValue();        return;      }       if (!complexMapKeySerialization) {        out.beginObject();        for (Map.Entry entry : map.entrySet()) {          out.name(String.valueOf(entry.getKey()));          valueTypeAdapter.write(out, entry.getValue());        }        out.endObject();        return;      }       //...}

因为map的泛型在开始时并不知道key和value的类型是什么,所以在MapTypeAdapterFactory类初始化的时候,valueAdapter实际上是ObjectTypeAdapter方法。我们看下具体write方法:

@Override public void write(JsonWriter out, Object value) throws IOException {    if (value == null) {      out.nullValue();      return;    }     TypeAdapter typeAdapter = (TypeAdapter) gson.getAdapter(value.getClass());    if (typeAdapter instanceof ObjectTypeAdapter) {      out.beginObject();      out.endObject();      return;    }     typeAdapter.write(out, value);  }

因为value==null,所以最后调用JsonWriter.nullValue();

  public JsonWriter nullValue() throws IOException {    if (deferredName != null) {      if (serializeNulls) {        writeDeferredName();      } else {        deferredName = null;        return this; // skip the name and the value      }    }    beforeValue();    out.write("null");    return this;  }

到这里大家就明白了吧,我们没有配置serializeNulls,这里的serializeNulls==false,所以后面分支的注释已经说了:如果对于null值,会把它的name置空,跳过,也就是最后不输出。

问题根因大家知道了,解决办法应该有好几个。

(1)最常用的就是自定义一个map的adapter,让Gson启动加载,上篇文章自定义的string的适配器,是不起作用的。

(2)重写MapTypeAdapterFactory类。

(3)改写JsonWriter类。

因为Gson很多类都是final的,无法继承覆写,还是使用第一个比较简单。下面是我写的自定义map适配器:

public class MyMapTypeAdapter<K, V> extends TypeAdapter<Map>>{     @Override    public void write(JsonWriter out, Map map) throws IOException    {        if (map == null)        {            out.nullValue();            return;        }         out.beginObject();        for (Map.Entry entry : map.entrySet())        {            out.name(String.valueOf(entry.getKey()));                        //核心代码在这里,如果value是null,输出空字符串            Object value = (entry.getValue() == null) ? "" : entry.getValue();                        new Gson().getAdapter(Object.class).write(out, value);        }        out.endObject();        return;     }     @Override    public Map read(JsonReader var1) throws IOException    {        // TODO Auto-generated method stub        return null;    } }

运行结果[{"name":"","id":"123"},{"name":"","id":"123"},{"name":"","id":"123"}]

72f4cc50fa81d84673d0c7ea6c9a4dd9.png

到这里,就解决了Map的value中为空就不输出的问题。

上面有个细节,就是为啥Gson不对ObjectTypeAdapter中的null值提供写为""的方法?因为我们常说的null其实是一种像量子态的引用类型,你可以说它没有类型,但是你又可以把它转为任何类型。

Gson不知道你传给它的null到底是(String)null,还是(Integer)null,也许string类型的null想变成"",也许Integer类型的null就想变成0。所以自由权还是给使用者,自己定义吧。

如果有人使用阿里的fastjson,对于map的null值处理也要自定义filter才行,默认的SerializerFeature.WriteNullStringAsEmpty不行。


作者:kuailebuzhidao

来源:

https://blog.csdn.net/kuailebuzhidao/article/details/109743696

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值