Java递归遍历嵌套JSON按ID替换指定字段值问题排查
问题根因
修改不生效的核心原因有三个:
- 递归过程中如果将org.json的
JSONObject/JSONArray转成Gson对象或Java实体类再修改,操作的是反序列化生成的深拷贝副本,和原JSON对象完全隔离,修改不会同步 - 遍历逻辑只覆盖了最外层rules节点,没有递归穿透value数组内部嵌套的子
condition/rules结构,深层匹配节点不会被处理 - 遍历数组时如果先调用
toList()转成Java集合再操作,操作的是拷贝出的集合对象,修改不会回写到原JSONArray
正确实现方案
采用纯org.json原生API递归,全程操作原对象引用,无额外序列化/反序列化开销,逻辑如下:
- 递归方法接收任意类型节点(支持对象、数组、基础值类型)
- 遇到数组节点:遍历所有元素,逐个递归处理
- 遇到对象节点:首先判断是否满足
field字段值为stage.id且存在value数组的匹配规则,满足则遍历value数组,将id为123的对象的name字段直接修改为xyz;随后遍历对象所有字段值,逐个递归处理(保证覆盖所有嵌套的子规则结构) - 遇到字符串、数字、布尔、null等基础类型节点,直接跳过不处理
完整实现代码:
import org.json.JSONArray; import org.json.JSONObject; public class NestedJsonModifier { public static void processNode(Object node) { // 处理数组类型节点 if (node instanceof JSONArray) { JSONArray array = (JSONArray) node; for (int i = 0; i < array.length(); i++) { processNode(array.get(i)); } return; } // 处理对象类型节点 if (node instanceof JSONObject) { JSONObject jsonObj = (JSONObject) node; // 匹配目标路径规则 if (jsonObj.has("field") && "stage.id".equals(jsonObj.optString("field")) && jsonObj.get("value") instanceof JSONArray) { JSONArray valueArray = jsonObj.getJSONArray("value"); for (int i = 0; i < valueArray.length(); i++) { Object item = valueArray.get(i); if (item instanceof JSONObject) { JSONObject itemObj = (JSONObject) item; if ("123".equals(itemObj.optString("id"))) { // 直接操作原引用,修改自动同步 itemObj.put("name", "xyz"); } } } } // 递归遍历所有子字段,覆盖嵌套的condition/rules结构 for (String key : jsonObj.keySet()) { processNode(jsonObj.get(key)); } return; } // 基础值类型直接返回 } // 调用示例 public static void main(String[] args) { // 替换为实际输入的JSON字符串 String inputJson = ""; JSONObject root = new JSONObject(inputJson); processNode(root); // 输出格式化后的修改结果 System.out.println(root.toString(2)); } }
注意事项
- 不要在递归流程中混用Gson和org.json的对象模型,跨类库转换会生成拷贝对象,导致修改丢失
- 匹配到目标规则并完成修改后不能终止递归,必须继续遍历当前节点的所有子字段,否则深层嵌套的同规则节点会被遗漏
- 遍历
JSONArray时通过索引直接get/set操作,不要转成List后修改,避免操作拷贝对象导致修改不生效
内容的提问来源于stack exchange,提问作者Vinoth
相关产品推荐
相关产品推荐

