如何从含数组的JSON中获取带父键前缀的嵌套键值对
解决JSON嵌套结构(含数组)转带前缀键值对问题
原代码问题分析
- 处理JSON数组时,错误地将整个数组直接存入Map,同时递归遍历数组元素,导致键冲突或冗余数据
- 数组元素的键未添加索引标识,无法区分数组中不同位置的元素
- 键分隔符使用下划线
_,不符合需求中的点.分隔格式(如Group.class)
修复优化后的实现(基于org.json)
import org.json.JSONArray; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; import java.util.stream.IntStream; public class JsonFlattener { public static Map<String, String> flattenJson(Object json) { Map<String, String> result = new HashMap<>(); flatten(json, null, result); return result; } private static void flatten(Object object, String parentKey, Map<String, String> result) { if (object instanceof JSONObject) { JSONObject jsonObject = (JSONObject) object; jsonObject.keySet().forEach(childKey -> { String newKey = parentKey != null ? parentKey + "." + childKey : childKey; flatten(jsonObject.get(childKey), newKey, result); }); } else if (object instanceof JSONArray) { JSONArray jsonArray = (JSONArray) object; // 遍历数组元素,用父键+索引作为元素前缀 IntStream.range(0, jsonArray.length()) .forEach(index -> { String newKey = parentKey != null ? parentKey + "." + index : String.valueOf(index); flatten(jsonArray.get(index), newKey, result); }); } else { // 基础类型直接存入Map,跳过无父键的无效情况 if (parentKey != null) { result.put(parentKey, object.toString()); } } } }
关键修改说明
- 数组逻辑修复:移除存入整个数组的代码,改为遍历每个元素,用
父键.索引作为元素的前缀键,比如数组students的第一个元素键为students.0 - 分隔符调整:将下划线
_改为点.,匹配需求中的嵌套键格式 - 调用简化:对外提供
flattenJson入口方法,无需手动初始化Map,调用更便捷 - 边界处理:避免无父键的基础类型存入Map,减少无效数据
调用示例
public static void main(String[] args) { String jsonStr = "{\"Group\":{\"class\":\"A\",\"students\":[{\"name\":\"Alice\",\"age\":18},{\"name\":\"Bob\",\"age\":19}]}}"; JSONObject jsonObject = new JSONObject(jsonStr); Map<String, String> flatMap = JsonFlattener.flattenJson(jsonObject); flatMap.forEach((k, v) -> System.out.println(k + " = " + v)); }
输出结果:
Group.class = A Group.students.0.name = Alice Group.students.0.age = 18 Group.students.1.name = Bob Group.students.1.age = 19
更简洁的实现(基于Jackson)
如果项目已引入Jackson库,可利用其树遍历功能更高效实现:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.Map; public class JacksonJsonFlattener { private static final ObjectMapper mapper = new ObjectMapper(); public static Map<String, String> flattenJson(String jsonStr) throws Exception { Map<String, String> result = new HashMap<>(); JsonNode root = mapper.readTree(jsonStr); flatten(root, null, result); return result; } private static void flatten(JsonNode node, String parentKey, Map<String, String> result) { if (node.isObject()) { node.fields().forEachRemaining(entry -> { String newKey = parentKey != null ? parentKey + "." + entry.getKey() : entry.getKey(); flatten(entry.getValue(), newKey, result); }); } else if (node.isArray()) { for (int i = 0; i < node.size(); i++) { String newKey = parentKey != null ? parentKey + "." + i : String.valueOf(i); flatten(node.get(i), newKey, result); } } else if (node.isValueNode()) { if (parentKey != null) { result.put(parentKey, node.asText()); } } } }
该实现无需依赖org.json库,Jackson树模型对复杂JSON的处理性能更优,代码也更简洁。
内容的提问来源于stack exchange,提问作者elads11
相关产品推荐
相关产品推荐

