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

遍历JsonNode查找指定节点父节点:REST响应自定义反序列化需求

如何在Jackson的JsonNode中通过key值找到对应的value节点?

首先,先明确你的目标JSON结构(格式化后更清晰):

{
  "someField": [
    { "key": "foo", "value": { "left": "bar_left", "right": "bar_right" } },
    { "key": "foo2", "value": { "left": "bar_left2", "right": "bar_right2" } }
  ],
  "anotherField": [
    { "key": "foo3", "value": { "left": "bar_left", "right": "bar_right" } },
    { "key": "foo4", "value": { "left": "bar_left2", "right": "bar_right2" } }
  ],
  "someMoreField": {}
}

你需要根据唯一的key值找到对应的left和right,但JsonNode没有getParent()方法,所以得在遍历的时候手动跟踪父节点的引用。下面是几种可行的实现方式:

方法1:递归遍历(简洁易读)

递归是最直观的方式,在遍历每个节点时传递其父节点的引用,一旦找到目标key就返回对应的父节点:

public static JsonNode findParentByKey(JsonNode node, String targetKey, JsonNode parent) {
    // 处理对象节点
    if (node.isObject()) {
        // 检查当前节点是否包含目标key
        if (node.has("key") && node.get("key").asText().equals(targetKey)) {
            return parent;
        }
        // 遍历所有子字段
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            JsonNode result = findParentByKey(entry.getValue(), targetKey, node);
            if (result != null) {
                return result;
            }
        }
    } 
    // 处理数组节点
    else if (node.isArray()) {
        for (JsonNode element : node) {
            JsonNode result = findParentByKey(element, targetKey, node);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

// 使用示例
JsonNode rootNode = ...; // 你的根节点实例
JsonNode parentNode = findParentByKey(rootNode, "foo", null);
if (parentNode != null) {
    JsonNode valueNode = parentNode.get("value");
    String left = valueNode.get("left").asText();
    String right = valueNode.get("right").asText();
    System.out.println("Left: " + left + ", Right: " + right);
}

优点:代码简洁,逻辑清晰;缺点:如果JSON层级极深(比如超过JVM栈深度),会抛出StackOverflowError。

方法2:迭代式遍历(避免栈溢出)

如果你的JSON可能有非常深的层级,用迭代+栈的方式来跟踪父节点更安全:

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.Map;

public static JsonNode findParentByKeyIterative(JsonNode rootNode, String targetKey) {
    Deque<JsonNode> nodeStack = new ArrayDeque<>();
    Deque<JsonNode> parentStack = new ArrayDeque<>();
    
    nodeStack.push(rootNode);
    parentStack.push(null);
    
    while (!nodeStack.isEmpty()) {
        JsonNode current = nodeStack.pop();
        JsonNode parent = parentStack.pop();
        
        if (current.isObject()) {
            // 检查是否是目标节点
            if (current.has("key") && current.get("key").asText().equals(targetKey)) {
                return parent;
            }
            // 反向压栈保证遍历顺序和递归一致(可选)
            ArrayList<Map.Entry<String, JsonNode>> entries = new ArrayList<>(current.fields());
            Collections.reverse(entries);
            for (Map.Entry<String, JsonNode> entry : entries) {
                nodeStack.push(entry.getValue());
                parentStack.push(current);
            }
        } else if (current.isArray()) {
            ArrayList<JsonNode> elements = new ArrayList<>(current);
            Collections.reverse(elements);
            for (JsonNode element : elements) {
                nodeStack.push(element);
                parentStack.push(current);
            }
        }
    }
    return null;
}

// 使用示例
JsonNode parentNode = findParentByKeyIterative(rootNode, "foo");
if (parentNode != null) {
    JsonNode valueNode = parentNode.get("value");
    // 处理left和right...
}

优点:不会出现栈溢出问题,适合大型/深层JSON;缺点:代码比递归稍复杂。

方法3:精准遍历(最高效)

既然你知道JSON的结构是「根节点下的数组字段包含key和value对象」,可以直接遍历这些数组,跳过无关节点,效率最高:

import java.util.Iterator;
import java.util.Map;
import java.util.Optional;

public static Optional<JsonNode> findValueByKey(JsonNode rootNode, String targetKey) {
    // 遍历根节点的所有字段
    Iterator<Map.Entry<String, JsonNode>> rootFields = rootNode.fields();
    while (rootFields.hasNext()) {
        Map.Entry<String, JsonNode> entry = rootFields.next();
        JsonNode fieldValue = entry.getValue();
        if (fieldValue.isArray()) {
            // 遍历数组中的每个对象
            for (JsonNode item : fieldValue) {
                if (item.has("key") && item.get("key").asText().equals(targetKey)) {
                    return Optional.of(item.get("value"));
                }
            }
        }
    }
    return Optional.empty();
}

// 使用示例
Optional<JsonNode> valueNodeOpt = findValueByKey(rootNode, "foo");
valueNodeOpt.ifPresent(valueNode -> {
    String left = valueNode.get("left").asText();
    String right = valueNode.get("right").asText();
    System.out.println("Left: " + left + ", Right: " + right);
});

优点:遍历范围最小,性能最好;缺点:依赖固定的JSON结构,如果结构变化需要调整代码。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:58:08