com.alibaba.fastjson转换JSON数据后顺序与原JSON字符串顺序不一致原因分析

ぐ巨炮叔叔 提交于 2020-01-11 20:54:55

转换字符串示例:

		String array2 = "{'i':'2','b':'3'}";
		JSONObject parseObject = JSON.parseObject(array2);

结果:

{"b":"3","i":"2"}

我们会发现顺序与原来的字符串顺序不一致。

通过DEBUG去com.alibaba.fastjson.parser.DefaultJSONParser的下述方法

    public Object parse(Object fieldName) {
        final JSONLexer lexer = this.lexer;
        switch (lexer.token()) {
            case SET:
                lexer.nextToken();
                HashSet<Object> set = new HashSet<Object>();
                parseArray(set, fieldName);
                return set;
            case TREE_SET:
                lexer.nextToken();
                TreeSet<Object> treeSet = new TreeSet<Object>();
                parseArray(treeSet, fieldName);
                return treeSet;
            case LBRACKET:
                JSONArray array = new JSONArray();
                parseArray(array, fieldName);
                if (lexer.isEnabled(Feature.UseObjectArray)) {
                    return array.toArray();
                }
                return array;
            case LBRACE:
//重点就是此行的lexer.isEnabled(Feature.OrderedField)=false
                JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
                return parseObject(object, fieldName);
//            case LBRACE: {
//                Map<String, Object> map = lexer.isEnabled(Feature.OrderedField)
//                        ? new LinkedHashMap<String, Object>()
//                        : new HashMap<String, Object>();
//                Object obj = parseObject(map, fieldName);
//                if (obj != map) {
//                    return obj;
//                }
//                return new JSONObject(map);
//            }
            case LITERAL_INT:
                Number intValue = lexer.integerValue();
                lexer.nextToken();
                return intValue;
            case LITERAL_FLOAT:
                Object value = lexer.decimalValue(lexer.isEnabled(Feature.UseBigDecimal));
                lexer.nextToken();
                return value;

重点就是此行的lexer.isEnabled(Feature.OrderedField)=false,打开JSONObject的源码构造方法可以发现当ordered参数值为false时使用的是HashMap存放数据。

    public JSONObject(int initialCapacity, boolean ordered){
        if (ordered) {
            map = new LinkedHashMap<String, Object>(initialCapacity);
        } else {
            map = new HashMap<String, Object>(initialCapacity);
        }
    }

hashmap是数组加链表结构,根据key的hash算法确定在数组中的位置,当发生hash冲突的时候,根据二叉树或者红黑树构成链表。所以是有序的,key确定,位置也就确定了。

如果要实现转换前的数据顺序与转换后的数据顺序一致,可以使用如下方式:

		String array2 = "{'i':'2','b':'3'}";
		JSONObject parseObject = JSON.parseObject(array2, Feature.OrderedField);

此时会使用LinkedHashMap,LinkedHashMap的内部维持了一个双向链表,保存了数据的插入顺序,遍历时,先得到的数据便是先插入的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!