JsonObject存入顺序和输出顺序不一样问题-豆果

本文介绍了一种通过继承JsonObject并使用LinkedHashMap替代HashMap的方法,来确保JSON对象中元素的输入顺序和输出顺序保持一致。该方法适用于需要保持JSON数据有序性的应用场景。

##JsonObject的输入顺序和输出顺序不一样问题 ###问题原因在于JsonObject的默认实现的是用HashMap,所以我们得把他的构造函数用LinkedHashMap重写

  • 好像是可以修改JsonObject的源码的构造函数,但我没试过,也不建议这么做。
  • 我的方法是继承JsonObject类,然后重写构造方法。
  public class MyJSONObject extends JSONObject {
    private LinkedHashMap<Object, Object> mHashMap;

    public MyJSONObject() {
        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 String  getKey(String key) throws JSONException{
        return mHashMap.get(key).toString();
    }

    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());
    }

}


转载于:https://my.oschina.net/lcyanxi/blog/1514409

### 如何在使用 `JsonObject` 时保持键值对的顺序 默认情况下,在许多编程语言的标准库中,`JsonObject` 或类似的对象可能会保留其键值对的插入顺序。这是因为底层数据结构通常基于哈希表(如 Java 的 `HashMap`),而哈希表本身保证有序性。 #### 解决方案一:使用支持有序性的替代类 在某些语言中,可以找到专门设计用于维护插入顺序的数据结构来代替标准的 JSON 对象容器。例如: - **Java**: 使用 `LinkedHashMap` 而是普通的 `HashMap` 来存储键值对[^1]。由于 `LinkedHashMap` 维护了一个双向链表以记录元素的插入顺序,因此它能够很好地满足需求。 ```java import java.util.LinkedHashMap; import org.json.JSONObject; public class Main { public static void main(String[] args) throws Exception { LinkedHashMap<String, Object> map = new LinkedHashMap<>(); map.put("first", "value1"); map.put("second", "value2"); JSONObject jsonObject = new JSONObject(map); System.out.println(jsonObject.toString(4)); // 输出按照 first second 的顺序排列 } } ``` - **Python**: 利用内置的 `collections.OrderedDict` 类型作为字典的基础构建自定义 JSON 编码器[^2]。从 Python 3.7 开始,默认字典也已经实现了保持插入顺序的功能,但这并意味着所有的第三方库都会自动遵循这一特性;如果遇到问题,则显式指定 OrderedDict 是更安全的选择。 ```python from collections import OrderedDict import json data = OrderedDict() data['key1'] = 'value1' data['key2'] = 'value2' json_string = json.dumps(data, indent=4) print(json_string) # 结果中的 key1 将位于 key2 前面 ``` #### 解决方案二:手动控制序列化过程 当无法更改原始数据结构或者使用的框架允许替换内部实现的时候,可以通过调整最终输出阶段的方式间接达到目的——即先收集所有字段到一个列表里再逐一写入目标文件/字符串流之中[^3]。 这种方法虽然稍微复杂一点,但它提供了极大的灵活性,并且几乎适用于任何环境下的情况。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值