关于android 的org.json类JsonObject解析值为null的出现的问题

相信org.json包下的jsonObject有些人比较熟悉了,它是android原生的json解析类,先看下org.json 包的结构,比较简单:
这里写图片描述
今天在用这个对象注意到了这个问题:在对服务器返回来的JsonObject做解析时,我用JsonObject.getXXX()方法取返回值,之前没注意,log中经常抛warn类型的异常:JsonException.原来这是get这种方法均会抛出的异常:

    public Object get(String name) throws JSONException {
        Object result = nameValuePairs.get(name);
        if (result == null) {
            throw new JSONException("No value for " + name);
        }
        return result;
    }

无论是getString(),getBoolean等方法,均会有类似上述异常抛出。而我要实现的功能是将jsonObject转化成实体bean,但是json中有值为null的情况(我需要将null转化成”“或者0),导致程序被try catch掉,不能继续转化。这是我的代码:

为了解决这个问题,我本着这个android原生的解析类作者不可能这么sb的想法,心想肯定有其他方法可以替代,很快就找到了opt方法,这是Json.opt() 的方法说明:

      Returns the value mapped by {@code name}, or null if no such mapping exists.

意思是说如果没有匹配name的值的话,就会return null(注意,坑就在这里!)

我非常高兴找到了“解决办法”,于是就把代码全部换成了opt相关的方法,并有iterater寻找为null的值,如果为null,根据健的类型做相应的处理:

        Iterator<String> keys = jsonObject.keys();
        while (keys.hasNext()) {
            String key = keys.next();

            Object value = jsonObject.opt(key);
            if(value==null) {
                if("type".equals(key)) {
                    value = 0;
                } else if("name".equals(key)) {
                    value = null;
                }
            }
         }

结果通过log打印转化后的实体发现,type和name里面竟然还是null,根本没有得到转化!?于是我开启断点调试,发现通过opt返回的值竟然是”null” 而不是null。怎么会这样?原因之后解释。我通过进一步使用发现,使用JsonObject.optInt(),JsonObject.optLong()均没有问题,通过重载方法optInt(String name,int fallBack)可以指定默认值:

int value = jsonObject.optInt("type", 0);

如果type健的json值为null的话,value为0,但是如果使用optString(String name,String fallBack)就会有问题:

String name = jsonObject.optString("realName", "");

结果name的值为”null”而不是” ” 哎呀我就是纳闷了。决定晚上回去后再一探究竟。


回去后。。。。

这是optString的源码:
    public String optString(String name, String fallback) {
        Object object = opt(name);
        String result = JSON.toString(object);
        return result != null ? result : fallback;
    }

调试进入后发现如果健为name的值为null的话,opt(name)这个返回的object直接为”null”,所以问题出现opt(name)这个方法里面

opt(String)源码:
    public Object opt(String name) {
        return nameValuePairs.get(name);
    }
    @Override public V get(Object key) {
        /*
         * This method is overridden to eliminate the need for a polymorphic
         * invocation in superclass at the expense of code duplication.
         */
        if (key == null) {
            HashMapEntry<K, V> e = entryForNullKey;
            if (e == null)
                return null;
            if (accessOrder)
                makeTail((LinkedEntry<K, V>) e);
            return e.value;
        }

        int hash = Collections.secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
                e != null; e = e.next) {
            K eKey = e.key;
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                if (accessOrder)
                    makeTail((LinkedEntry<K, V>) e);
                return e.value;
            }
        }
        return null;
    }

看出关键就在tab这个HashTabEntry,e.value返回了”null”,至于为啥,只有去看hashmap的原理了。。。

我在看stackoverflow找到了一种说法:
这里写图片描述
说是这是一个org.json的bug,确实,只有string会出现这个情况已经算bug了,解决方式是使用json.isNull()这个方法,通过这个判断值是否是null,如果是,则可以做处理:图中是直接将null返回,而我的功能就是返回空值,这就解决了这个坑了。。。

回过头来看之前所说的坑:opt(String name)说明:

      Returns the value mapped by {@code name}, or null if no such mapping exists.

仔细想想,意思是说返回map中存在的值(通过健name),或者null,如果没有这个name所对应的值存在的话。。。意思说,只有name不存在这个情况,才会返回null。我去,这话说得。。。。

关于hashmap的原理,容小白的我懂了再补充,究竟为啥e里面就存了个”null”了?

如果要用json解析框架,就不会出现上述问题,但框架有框架的限制,自带的有比较高的灵活性,其中的优劣,只有看实际情况和个人取舍了,晚上跟一朋友争论用框架的好处与劣处,结果。。。开撕 了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值