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
相关产品推荐
相关产品推荐

