org.json源码分析及增强(二)——org.json.JSONException: Duplicate key问题处理

前端之家收集整理的这篇文章主要介绍了org.json源码分析及增强(二)——org.json.JSONException: Duplicate key问题处理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

org.json.JSONException: Duplicate key问题的出现

当使用JSONObject处理如json{\"key\" : 1,\"key\" : 2}"这样的JSON数据格式的字符串时,或使用JSONArray处理json[{\"key\" : 1,\"key\" : 2},{\"key\" : 3,\"key\" : 4}]的数组字符串时,org.json.JSONException: Duplicate key的问题就出现了,原因首先是JSON数据格式不规范,本就不应该包含相同的key名,另外,JSONObject内部使用的是一个map数据结构,是不允许有同样的key存在的,因此,通过抛出JSONException异常来警告使用者。主要的源码如下:

public JSONObject putOnce(String key,Object value) throws JSONException {
        if (key != null && value != null) {
            if (this.opt(key) != null) {
                throw new JSONException("Duplicate key \"" + key + "\"");
            }
            this.put(key,value);
        }
        return this;
    }

通过this.opt(key) != null来进行重复key的判断,但原生JS对于重复key的JSON串的处理过程是什么样子的呢?

还原原生JS的处理

我们通过浏览器的控制台写一段JS进行测试:

var data = "[{\"key\" : 1,\"key\" : 4}]";
eval("("+data+")");

运行结果如下:

可以看到JS的处理是会保留最后一对重复key的值作为key属性的值。

模仿原生JS的处理

首先说明你可以通过修改和继承已有的JSONArray、JSONObject和JSONTokener类来完成模仿JS的处理,但实际上你所处理的JSON串是极不规范的。
主要的注意细节和方法如下:
(1)为了继承JSONArray类,并获取到map对象,需要将JSONArray.java中的ArrayList myArrayList由private修改为protected;
(2)通过继承重载JSONObject类的putOnce方法,将重复key的检查逻辑去掉,这样就完成了JSONObject对于重复key的支持
(3)对于JSONArray比较麻烦一些,需要一个继承重载JSONTokener类的nextValue方法的子类,并且还需要构建JSONObject和JSONArray子类的相关构造函数
参考代码如下:
JSONArrayIgnoreDuplicates类:

public class JSONArrayIgnoreDuplicates extends JSONArray{

    public JSONArrayIgnoreDuplicates(){
        super();
    }

    public JSONArrayIgnoreDuplicates(String json){
        this(new JSONTokenerIgnoreDuplicates(json));
    }

     public JSONArrayIgnoreDuplicates(JSONTokenerIgnoreDuplicates x) throws JSONException {

         if (x.nextClean() != '[') {
             throw x.SyntaxError("A JSONArray text must start with '['");
         }

         if (x.nextClean() != ']') {
                x.back();
                for (;;) {
                    if (x.nextClean() == ',') {
                        x.back();
                        this.myArrayList.add(JSONObjectIgnoreDuplicates.NULL);
                    } else {
                        x.back();
                        this.myArrayList.add(x.nextValue());
                    }
                    switch (x.nextClean()) {
                    case ',':
                        if (x.nextClean() == ']') {
                            return;
                        }
                        x.back();
                        break;
                    case ']':
                        return;
                    default:
                        throw x.SyntaxError("Expected a ',' or ']'");
                    }
                }
            }
     }

}

JSONObjectIgnoreDuplicates类:

public class JSONObjectIgnoreDuplicates extends JSONObject {
    public JSONObjectIgnoreDuplicates(String json) {
        super(json);
    }

    public JSONObjectIgnoreDuplicates(JSONTokenerIgnoreDuplicates x) {
        super(x);
    }

    public JSONObject putOnce(String key,Object value) throws JSONException {
        if (key != null && value != null) {
            if (this.opt(key) != null ) {
                System.out.println("Duplicate key \"" + key + "\"");
            }
            this.put(key,value);
        }

        return this;
    }
}

JSONTokenerIgnoreDuplicates类:

public class JSONTokenerIgnoreDuplicates extends JSONTokener {

    public JSONTokenerIgnoreDuplicates(String s) {
        super(s);
    }

    @Override
     public Object nextValue() throws JSONException {
            char c = this.nextClean();
            String string;

            switch (c) {
                case '"':
                case '\'':
                    return this.nextString(c);
                case '{':
                    this.back();
                    return new JSONObjectIgnoreDuplicates(this);
                case '[':
                    this.back();
                    return new JSONObjectIgnoreDuplicates(this);
            }

            StringBuilder sb = new StringBuilder();
            while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
                sb.append(c);
                c = this.next();
            }
            this.back();

            string = sb.toString().trim();
            if ("".equals(string)) {
                throw this.SyntaxError("Missing value");
            }
            return JSONObjectIgnoreDuplicates.stringToValue(string);
        }

}

测试代码如下:

JSONArrayIgnoreDuplicates array = new JSONArrayIgnoreDuplicates("[{\"key\" : 1,\"key\" : 4}]");
         System.out.println(array.toString());

运行结果:

猜你在找的Json相关文章