固定JSONObject.toString()键值对顺序

org.json.JSONObject相信不少人都用过,例如:服务端返回给客户端的数据格式是JSONObject的,那咱们经过对它进行解析,把它显示在界面上。html

有时候但愿服务器跟客户端通讯的JSONObjectt的键值对顺序是固定的。json

例如:数组

客户端提交一个JSONObject格式的数据,里面有三个键值对,分别是"a":"a"    "b":"b"      "c":"c"服务器

服务端原封不动返回给客户端,这个客户端但愿接到的是这样的app

{"a":"a","b":"b","c":"c"}ide


但JSONObject的键值对顺序几乎不能肯定的,无规律可循,验证以下:this

1. <pre name="code" class="html">        code

JSONObject object=new JSONObject();
        try {
            object.putOpt("b", "b");
            object.putOpt("a", "a");
            object.putOpt("c", "c");
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }htm

object.toString(),获得的是rem

{"b":"b","c":"c","a":"a"}

与put进去时候的顺序不一致。

2.

    JSONObject object=new JSONObject();
        try {
            object.putOpt("1", "1");
            object.putOpt("2", "2");
            object.putOpt("3", "3");
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

object.toString(),获得的是

{"3":"3","2":"2","1":"1"}

与put进去时候的顺序不一致

3.

    JSONObject object=new JSONObject();
        try {
            object.putOpt("我", "我");
            object.putOpt("你", "你");
            object.putOpt("他", "他");
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

object.toString(),获得的是

{"你":"你","他":"他","我":"我"}

与put进去时候的顺序不一致。

以上三个例子,不管键和值是数字、字母仍是中文,JSONObject put进去的顺序喝toString获得的顺序,是不一致的。

 

若是还有疑问,咱们看看JSONObject的源码吧。

先看构造方法:

    public JSONObject() {
        nameValuePairs = new HashMap<String, Object>();
    }

再看putOpt 以及put方法:

    public JSONObject putOpt(String name, Object value) throws JSONException {
        if (name == null || value == null) {
            return this;
        }
        return put(name, value);
    }

    public JSONObject put(String name, Object value) throws JSONException {
        if (value == null) {
            nameValuePairs.remove(name);
            return this;
        }
        if (value instanceof Number) {
            // deviate from the original by checking all Numbers, not just floats & doubles
            JSON.checkDouble(((Number) value).doubleValue());
        }
        nameValuePairs.put(checkName(name), value);
        return this;
    }

这下可明白了吧,其实JSONObject本质是用HashMap实现的,而HashMap是散列的,是链式存储结构。

HashMap的存储过程,根据该元素自身提供的hashcode计算出散列值(在这一点上,就能够知道,元素放进去的位置是没法肯定的,只有在获取hashcode后才知道),该值就是数组的下标,而后将该元素放入数组位置的链表中。


那么如何固定它的顺序呢,put进去是咱们想要的呢?有两个方法:自定义JSONObject(不用HashMap改用LinkHashMap实现)或使用com.alibaba.fastjson.annotation.JSONType标注

1.自定义JSONObject(不用HashMap改用LinkHashMap实现),LinkedHashMap是有序的,代替无序的HashMap,把父类用到HashMap的地方都改为LinkedHashMap便可,主要是put跟toString的几个方法。

public class MyJSONObject extends JSONObject {

    private LinkedHashMap<Object, Object> mHashMap;

    public ChatMsgJSONObject() {
        mHashMap = new LinkedHashMap<Object, Object>();
    }

    @Override
    public JSONObject put(String name, boolean value) throws JSONException {
        // TODO Auto-generated method stub
        return put(name, value);
    }

    @Override
    public JSONObject put(String name, double value) throws JSONException {
        // TODO Auto-generated method stub
        return put(name, value);
    }

    @Override
    public JSONObject put(String name, int value) throws JSONException {
        // TODO Auto-generated method stub
        return put(name, value);
    }

    @Override
    public JSONObject put(String name, long value) throws JSONException {
        // TODO Auto-generated method stub
        return put(name, value);
    }

    public JSONObject put(String key, Object value) throws JSONException {
        if (key == null) {
            throw new JSONException("Null key.");
        }
        if (value != null) {
            testValidity(value);
            mHashMap.put(key, value);
        } else {
            remove(key);
        }
        return this;
    }

    public Object remove(String key) {
        return mHashMap.remove(key);
    }

    static void testValidity(Object o) throws JSONException {
        if (o != null) {
            if (o instanceof Double) {
                if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
                    throw new JSONException("JSON does not allow non-finite numbers.");
                }
            } else if (o instanceof Float) {
                if (((Float) o).isInfinite() || ((Float) o).isNaN()) {
                    throw new JSONException("JSON does not allow non-finite numbers.");
                }
            }
        }
    }

    public String toString() {
        try {
            Iterator<Object> keys = mHashMap.keySet().iterator();
            StringBuffer sb = new StringBuffer("{");

            while (keys.hasNext()) {
                if (sb.length() > 1) {
                    sb.append(',');
                }
                Object o = keys.next();
                sb.append(quote(o.toString()));
                sb.append(':');
                sb.append(valueToString(mHashMap.get(o)));
            }
            sb.append('}');
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    static String valueToString(Object value) throws JSONException {
        if (value == null || value.equals(null)) {
            return "null";
        }
        if (value instanceof JSONStringer) {
            Object o;
            try {
                o = ((JSONStringer) value).toString();
            } catch (Exception e) {
                throw new JSONException(e.getMessage());
            }
            if (o instanceof String) {
                return (String) o;
            }
            throw new JSONException("Bad value from toJSONString: " + o);
        }
        if (value instanceof Number) {
            return numberToString((Number) value);
        }
        if (value instanceof Boolean || value instanceof JSONObject || value instanceof JSONArray) {
            return value.toString();
        }
        if (value instanceof Map) {
            return new JSONObject((Map) value).toString();
        }
        if (value instanceof Collection) {
            return new JSONArray((Collection) value).toString();
        }
        return quote(value.toString());
    }

}

相关文章
相关标签/搜索