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

Java解析含重复键的嵌套JSON问题求助

解决Jackson流式API解析重复键嵌套JSON的问题

我完全懂你的困扰——默认情况下Jackson解析JSON时遇到重复键会直接覆盖之前的值,所以你只能拿到第一个"A"的内容。别担心,咱们调整下代码逻辑,就能捕获所有重复键对应的"A"值了。

问题根源

你的JSON外层有两个重复的"C"键,普通流式遍历会因为重复键覆盖机制,导致第二个"C"下的内容被直接忽略。我们需要逐层遍历嵌套对象,主动处理每个字段,而不是依赖默认的覆盖逻辑。

修改后的代码

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.File;
import java.io.IOException;

public class JacksonJson {
    public static void main(String args[]) throws IOException {
        JsonFactory factory = new JsonFactory();
        // 显式开启允许重复键(Jackson默认允许,但显式声明更稳妥,适配不同版本)
        factory.enable(JsonParser.Feature.ALLOW_DUPLICATE_NAMES);
        JsonParser parser = factory.createParser(new File("a.json"));
        
        parser.nextToken(); // 跳过根对象的起始符号 "{"
        
        while (parser.nextToken() != JsonToken.END_OBJECT) {
            String fieldName = parser.getCurrentName();
            if ("Data".equals(fieldName)) {
                parser.nextToken(); // 进入Data对象内部
                // 遍历Data下的所有字段,包括重复的"C"
                while (parser.nextToken() != JsonToken.END_OBJECT) {
                    String dataField = parser.getCurrentName();
                    if ("C".equals(dataField)) {
                        parser.nextToken(); // 进入当前C对象内部
                        // 遍历C对象下的字段
                        while (parser.nextToken() != JsonToken.END_OBJECT) {
                            String cField = parser.getCurrentName();
                            if ("S".equals(cField)) {
                                parser.nextToken(); // 进入S对象内部
                                // 遍历S对象下的字段,寻找"A"
                                while (parser.nextToken() != JsonToken.END_OBJECT) {
                                    String sField = parser.getCurrentName();
                                    if ("A".equals(sField)) {
                                        parser.nextToken(); // 移动到"A"对应的值位置
                                        System.out.println("Value : " + parser.getText());
                                    } else {
                                        // 跳过不需要处理的子对象(比如"M")
                                        parser.skipChildren();
                                    }
                                }
                            } else {
                                // 跳过C对象下其他无关字段
                                parser.skipChildren();
                            }
                        }
                    } else {
                        // 跳过Data对象下其他无关字段
                        parser.skipChildren();
                    }
                }
            } else {
                // 跳过根对象下其他无关字段
                parser.skipChildren();
            }
        }
        parser.close();
    }
}

代码核心逻辑说明

  • 逐层嵌套遍历:从根对象开始,一层一层进入Data→C→S,确保每个重复的C都被单独处理,不会被前一个覆盖
  • 显式允许重复键:通过factory.enable(JsonParser.Feature.ALLOW_DUPLICATE_NAMES)确保Jackson不会因为重复键抛出异常(兼容不同版本的Jackson)
  • 跳过无关子对象:用parser.skipChildren()快速跳过不需要处理的M对象,避免无效遍历,提升解析效率

运行结果

执行这段代码后,你会看到两个"A"的值都被正确输出:

Value : first
Value : Second

如果需要把这些值收集起来后续使用,你可以初始化一个List<String>,把每个parser.getText()添加到列表中即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:52:41