Groovy JSONSlurper:如何遍历多层级对象与数组?
Groovy处理固定层级JSON的实用方案
一、JSONPath vs Map:选择建议
- 原生Map/List遍历:针对你这种层级固定(最多5层)、元素结构明确的场景,优先用Groovy原生的Map和List操作。语法直观,不需要额外引入依赖,性能更优,遇到单个对象直接取key,数组就循环遍历,调试也方便。
- JSONPath:更适合结构不固定、需要复杂查询的场景。对于固定层级的JSON,反而会增加语法复杂度,还要额外引入Jayway JsonPath这类依赖,完全没必要。
二、获取各层级键值的方法
Groovy用JsonSlurper解析JSON后,会将对象转为LinkedHashMap,数组转为ArrayList,直接通过层级访问+循环就能拿到所有层级的键:
- 根层级键:
json.keySet() - 子层级键:
- 若为单个对象:
json.parentKey.keySet() - 若为数组:遍历数组元素后,对每个元素取
element.keySet()
- 若为单个对象:
三、扁平化数据提取示例与技巧
简化版JSON示例
{ "root": { "level1": [ { "level2": { "level3": "value1", "level3_2": "value2" } }, { "level2": { "level3": "value3" } } ], "level1_single": { "level2": { "level3": "value4" } } } }
扁平化提取实现代码
import groovy.json.JsonSlurper def jsonStr = ''' { "root": { "level1": [ { "level2": { "level3": "value1", "level3_2": "value2" } }, { "level2": { "level3": "value3" } } ], "level1_single": { "level2": { "level3": "value4" } } } ''' def json = new JsonSlurper().parseText(jsonStr) def flatData = [] // 处理level1数组类型节点 json.root.level1.each { level1Item -> def level2Node = level1Item.level2 flatData << [ root_key: "root", level1_key: "level1", level2_keys: level2Node.keySet().join(","), level3_data: level2Node.collectEntries { k, v -> [(k): v] } ] } // 处理level1单个对象类型节点 def level1SingleNode = json.root.level1_single def level2SingleNode = level1SingleNode.level2 flatData << [ root_key: "root", level1_key: "level1_single", level2_keys: level2SingleNode.keySet().join(","), level3_data: level2SingleNode.collectEntries { k, v -> [(k): v] } ] // 输出结果 flatData.each { println it }
核心实用技巧
- 区分对象/数组:用
instanceof判断类型,数组就循环遍历,对象直接取键值,比如:if (node instanceof List) { node.each { item -> 处理逻辑 } } else { 直接处理node的键值 } - 通用递归遍历:如果不想写多层嵌套代码,可封装递归函数处理任意固定层级,自动收集扁平化数据:
def flattenNode(def node, String currentPath = "", def result = []) { if (node instanceof Map) { node.each { k, v -> def newPath = currentPath ? "${currentPath}.${k}" : k if (v instanceof Map || v instanceof List) { flattenNode(v, newPath, result) } else { result << [full_path: newPath, key: k, value: v] } } } else if (node instanceof List) { node.eachWithIndex { item, idx -> flattenNode(item, "${currentPath}[${idx}]", result) } } return result } // 调用示例 def fullFlatResult = flattenNode(json) fullFlatResult.each { println it } - 空指针防护:用Groovy的安全导航操作符
?.,比如json.root?.level1?.each,避免某层级为null时抛出异常。
内容的提问来源于stack exchange,提问作者Pauliesyllabic
相关产品推荐
相关产品推荐

