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

如何生成含未扁平化JSON列表的嵌套JSON?求Java解决方案

多级JSON对象嵌套转换解决方案

核心思路

  • 构建索引映射:先把输入列表中所有一级对象的键(如key1、key2)和对应的JSON对象存入HashMap,后续可快速通过键查找对应对象。
  • 递归替换引用:遍历每个JSON对象的所有值,若值为非空字符串且能在索引映射中找到对应键,则用该键对应的JSON对象替换这个字符串,继续递归处理替换后的对象,直到所有可替换的引用都处理完成。
  • 收集顶级对象:最终收集那些未被任何其他对象引用的顶级对象(即该对象的键没有出现在其他对象的值中),组成输出列表。

Java 实现示例(基于Jackson库)

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.*;

public class JsonNester {
    private static final ObjectMapper mapper = new ObjectMapper();

    public static List<JsonNode> nestJsonObjects(List<JsonNode> inputList) throws Exception {
        // 构建键到JSON对象的映射
        Map<String, JsonNode> keyToNodeMap = new HashMap<>();
        Set<String> referencedKeys = new HashSet<>();

        for (JsonNode node : inputList) {
            String key = node.fieldNames().next();
            JsonNode value = node.get(key);
            keyToNodeMap.put(key, value);
            // 收集所有被引用的键
            collectReferencedKeys(value, referencedKeys);
        }

        // 递归替换所有引用
        Map<String, JsonNode> processedNodes = new HashMap<>();
        for (Map.Entry<String, JsonNode> entry : keyToNodeMap.entrySet()) {
            processedNodes.put(entry.getKey(), replaceReferences(entry.getValue(), keyToNodeMap));
        }

        // 收集未被引用的顶级对象
        List<JsonNode> result = new ArrayList<>();
        for (Map.Entry<String, JsonNode> entry : processedNodes.entrySet()) {
            if (!referencedKeys.contains(entry.getKey())) {
                ObjectNode topNode = mapper.createObjectNode();
                topNode.set(entry.getKey(), entry.getValue());
                result.add(topNode);
            }
        }

        return result;
    }

    // 递归收集所有被引用的键
    private static void collectReferencedKeys(JsonNode node, Set<String> referencedKeys) {
        if (node.isObject()) {
            for (JsonNode value : node.values()) {
                if (value.isTextual() && !value.asText().isEmpty()) {
                    referencedKeys.add(value.asText());
                } else if (value.isObject()) {
                    collectReferencedKeys(value, referencedKeys);
                }
            }
        }
    }

    // 递归替换引用
    private static JsonNode replaceReferences(JsonNode node, Map<String, JsonNode> keyToNodeMap) {
        if (node.isObject()) {
            ObjectNode newNode = mapper.createObjectNode();
            for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext(); ) {
                Map.Entry<String, JsonNode> entry = it.next();
                JsonNode value = entry.getValue();
                if (value.isTextual() && !value.asText().isEmpty()) {
                    String refKey = value.asText();
                    if (keyToNodeMap.containsKey(refKey)) {
                        // 替换为对应的对象,并继续递归处理
                        newNode.set(entry.getKey(), replaceReferences(keyToNodeMap.get(refKey), keyToNodeMap));
                    } else {
                        newNode.set(entry.getKey(), value);
                    }
                } else if (value.isObject()) {
                    newNode.set(entry.getKey(), replaceReferences(value, keyToNodeMap));
                } else {
                    newNode.set(entry.getKey(), value);
                }
            }
            return newNode;
        }
        return node;
    }

    public static void main(String[] args) throws Exception {
        // 测试用例1输入
        String testInput1 = "[{\"key1\": {\"valueA\": \"\", \"valueB\": \"\"}},\n" +
                            "{\"key2\": {\"valueC\": \"key3\"}},\n" +
                            "{\"key3\": {\"valueD\": \"\", \"valueE\": \"\"}}]";
        List<JsonNode> input1 = mapper.readValue(testInput1, mapper.getTypeFactory().constructCollectionType(List.class, JsonNode.class));
        List<JsonNode> output1 = nestJsonObjects(input1);
        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(output1));

        // 测试用例2输入
        String testInput2 = "[{\"key1\": {\"valueA\": \"key2\"}},\n" +
                            "{\"key2\": {\"valueB\": \"key3\"}},\n" +
                            "{\"key3\": {\"valueC\": \"\", \"valueD\": \"\"}}]";
        List<JsonNode> input2 = mapper.readValue(testInput2, mapper.getTypeFactory().constructCollectionType(List.class, JsonNode.class));
        List<JsonNode> output2 = nestJsonObjects(input2);
        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(output2));
    }
}

推荐Java库

  • Jackson:Java生态中最常用的JSON处理库,提供灵活的树模型(JsonNode)和数据绑定功能,非常适合处理这种递归嵌套的JSON结构,上述示例就是基于Jackson实现的。
  • Gson:Google出品的JSON库,同样支持树模型(JsonObject)和递归操作,API简洁易懂,也能轻松实现需求中的转换逻辑。

测试结果验证

  • 测试用例1执行后,输出与预期一致:[{"key1": {"valueA": "", "valueB": ""}}, {"key2": {"valueC": {"valueD": "", "valueE": ""}}}]
  • 测试用例2执行后,输出与预期一致:[{"key1": {"valueA": {"valueB": {"valueC": "", "valueD": ""}}}}]

内容的提问来源于stack exchange,提问作者electronyoon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:27:39