Gson将json转Map的那些坑

版权声明:【分享也是一种提高】个人转载请在正文开头明显位置注明出处,未经作者同意禁止企业/组织转载,禁止私自更改原文,禁止用于商业目的。 https://blog.csdn.net/u010887744/article/details/51997336

        利用Gson将一串json数据转为Map格式,再get数据,相比很多人都做过。今天遇到一个“坑”,mark一下。

首先明确一点:Gson是可以将json转为Map的,并且Map的key是允许为Integer的。

    public void test() {
<span style="white-space:pre">	</span>String json1 = "{\"k1\"=\"外观\",\"k2\"=\"大厅\"}";
        Map<String, String> map = gson.fromJson(json1, HashMap.class);
        System.out.println(map.get("k1")); // 输出“外观”
        Map<Integer, String> map2 = new HashMap<>();
        map2.put(1, "value");
        System.out.println(map2.get(1)); // 输出“value”
    }

        接下来,看看这个“坑”。

 @Test
    public void testBug() { <span style="white-space:pre">	</span>String json2 = "{0=\"外观\",1=\"大厅\"}";
        Map<Integer, String> map = gson.fromJson(json2, HashMap.class);
        System.out.println(map.get(new Integer("1"))); // 输出 null
    }
        我们发现,当我们查找key为1的value时,返回值为null。但是调试分析可发现HashMap中确实是有key=1这个键值对的。这是为什么呢?百思不得解,随后,当我在testBug中这样查值,却能正常返回数据。

System.out.println(map.get("1")); // 输出 "大厅"
        这就显得很尴尬了,明明为Map指定了Integer类型,却变成了String类型,难道Gson默认这样不厚道的转换了一下,诚然,我最初的确这么想的,但随后就否决了,google不至于这么菜吧。

       细细一想,其实我们根本就没告诉Gson我们HashMap中key的类型,最后仅仅是将Gson转换成功的Map赋值给我们声明的Map,So如下转换就OK了。

 @Test
    public void testBug() {        String json2 = "{0=\"外观\",1=\"大厅\"}";
        System.out.println("===通过reflect告知Gson Map键值对的类型===");
        java.lang.reflect.Type type = new TypeToken<HashMap<Integer, String>>() {
        }.getType();
        Map<Integer, String> map2 = gson.fromJson(json2, type);
        System.out.println(map2.get(new Integer("1"))); // 输出 "大厅"
        System.out.println(map2.get("1")); // 输出 null
        // reflect确定类型后转换一切正常
    }
        相关测试代码详见:https://github.com/zxiaofan/JDK-Study/blob/master/src/java1/util/map/GsonToMap.java

        但另外一个问题又来了,既然Gson转换后的Map是<String,String>类型的,为何最后赋值给Map<Integer,String>没有任何编译错误呢?当我们直接写如下代码时会有编译错误,这个问题就有待考究了。

    更正(2018-03-03)

    但另外一个问题又来了,当没有指定类型的时候,int、double都会默认转成String,因为gson无法确定真实类型,指定类型后就会转换成实际类型了。当我们直接写如下代码时会有编译错误,是由于类型推断出实际类型应该是<String, String>,直接赋值给<Integer,String>当然编译会有问题。

        Map<String, String> m=new HashMap<>();
        m.put("w", "s");
        Map<Integer, String> map = m;
        路过的大神如有了解,请告知原因,不慎感激。


欢迎个人转载,但须在文章页面明显位置给出原文连接;
未经作者同意必须保留此段声明、不得随意修改原文、不得用于商业用途,否则保留追究法律责任的权利。

【 CSDN 】:csdn.zxiaofan.com
【GitHub】:github.zxiaofan.com

如有任何问题,欢迎留言。祝君好运!
Life is all about choices! 
将来的你一定会感激现在拼命的自己!



没有更多推荐了,返回首页