You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java按给定顺序读取JSON对象 按序提取键值父键列表

问题原因

顺序错乱的核心原因是你使用的org.json库默认JSONObject内部采用无序哈希表存储键值对,解析时不会保留JSON字符串中键的原始定义顺序,调用keys()遍历得到的是哈希排序后的结果,自然和原始JSON的书写顺序不匹配。另外你原有数组处理逻辑中提前将值转为字符串,会导致布尔、数字类型的值失真,也和预期输出不符。

修复方案

方案1:最小改动(继续使用org.json库)

org.json 从20180813版本开始,JSONObject提供了有序模式构造参数,传入true时会内部使用LinkedHashMap存储键值对,自动保留解析时的原始字段顺序,仅需少量修改原有代码即可:

import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;

// 测试JSON字符串a和你原有定义完全一致,此处省略重复定义
public static ArrayList<Object> extractKeysValues(String test, String parentKey) throws Exception {
    ArrayList<Object> arraylist = new ArrayList<Object>();
    if(test.charAt(0)=='{') {
        // 传入第二个参数true,启用有序存储,保留原始键顺序
        JSONObject json_object = new JSONObject(test, true);
        for (String key : json_object.keySet()) {
            Object value = json_object.get(key);
            arraylist.add(key);
            arraylist.add(value);
            arraylist.add(parentKey);
            if(value instanceof JSONObject || value instanceof JSONArray) {
                arraylist.addAll(extractKeysValues(value.toString(), key));
            }
        }
    } else if(test.charAt(0)=='[') {
        // JSONArray本身按索引有序,无需额外配置
        JSONArray json_array = new JSONArray(test);
        int json_array_length = json_array.length();
        for(int i=0;i<json_array_length;i++) {
            Object value = json_array.get(i);
            String idxKey = String.valueOf(i);
            arraylist.add(idxKey);
            arraylist.add(value);
            arraylist.add(parentKey);
            if(value instanceof JSONObject || value instanceof JSONArray) {
                arraylist.addAll(extractKeysValues(value.toString(), idxKey));
            }
        }
    }
    return arraylist;
}

如果你的org.json版本低于20180813,要么升级依赖版本,要么使用下面的方案2。

方案2:换用Jackson实现(兼容性更好)

如果不方便升级org.json版本,可以换用Jackson库做JSON解析,Jackson默认解析对象时就会用有序结构存储字段,自动保留原始定义顺序,不需要额外配置:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

public static ArrayList<Object> extractKeysValues(String jsonStr, String parentKey) throws Exception {
    ArrayList<Object> list = new ArrayList<>();
    ObjectMapper mapper = new ObjectMapper();
    JsonNode root = mapper.readTree(jsonStr);
    traverseNode(root, parentKey, list);
    return list;
}

private static void traverseNode(JsonNode node, String parentKey, ArrayList<Object> list) {
    if (node.isObject()) {
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            String key = entry.getKey();
            JsonNode value = entry.getValue();
            list.add(key);
            list.add(value);
            list.add(parentKey);
            if (value.isObject() || value.isArray()) {
                traverseNode(value, key, list);
            }
        }
    } else if (node.isArray()) {
        for (int i = 0; i < node.size(); i++) {
            JsonNode value = node.get(i);
            String idxKey = String.valueOf(i);
            list.add(idxKey);
            list.add(value);
            list.add(parentKey);
            if (value.isObject() || value.isArray()) {
                traverseNode(value, idxKey, list);
            }
        }
    }
}

两种方案执行后,遍历输出的字段顺序、值类型都会和你给出的预期结果完全匹配。

内容的提问来源于stack exchange,提问作者Praveen Samuel J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:51:20