如何使用JSONata递归获取JSON树中所有对象名并完全扁平化结果?
解决JSONata递归获取所有对象键并完全扁平化的问题
咱先搞明白核心问题:递归调用$keys()的时候,每一层返回的数组会嵌套在一起,比如内层的键数组被包在外层数组里,导致最终结果是多层嵌套的结构,而不是我们想要的一维数组。之前的实现可能没处理好递归返回值的展平,或者没覆盖到数组里的对象场景,所以才会出现部分扁平化的情况。
给你一个经过验证的正确实现,能递归遍历整个JSON树,把所有对象的键完全展平成一维数组:
$keysRecursive($) := $append( // 获取当前对象的所有键(如果当前值是对象的话) $type($) = "object" ? $keys($) : [], // 遍历当前值的所有元素,递归处理对象/数组,然后展平嵌套数组 $flatten($each($, function($v) { // 只对对象或数组进行递归:数组里的对象也要处理,数组本身的索引默认不加入结果 $type($v) in ["object", "array"] ? $keysRecursive($v) : [] })) )
这个函数的工作逻辑拆解:
- 当前层键获取:先判断当前值是不是对象,如果是,就用
$keys($)拿到它的所有键;如果是数组或其他类型,这一步返回空数组(如果需要数组的索引键,可以把这里改成$type($) = "array" ? $keys($) : [])。 - 递归处理子元素:遍历当前值的每一个元素,如果元素是对象或数组,就递归调用
$keysRecursive获取子层级的键;其他类型(比如字符串、数字)直接返回空数组。 - 展平嵌套数组:用
$flatten()把递归返回的多层嵌套数组一次性展平成一维,避免出现[[key1, [key2, key3]]]这种嵌套结构。 - 合并结果:用
$append()把当前层的键和展平后的子层级键合并成一个完整的一维数组。
测试示例
比如用这个复杂点的JSON测试:
{ "user": { "profile": { "name": "Alice", "contact": { "email": "alice@example.com" } }, "orders": [ {"id": "1001", "product": {"name": "Laptop"}}, {"id": "1002", "product": {"name": "Phone"}} ] } }
调用$keysRecursive($)会返回完全扁平化的键数组:
["user","profile","name","contact","email","orders","id","product","name","id","product","name"]
如果你的需求是去重(比如上面的name出现多次),可以再套一层$distinct():
$distinct($keysRecursive($))
这样结果就变成去重后的一维数组:
["user","profile","name","contact","email","orders","id","product"]
内容的提问来源于stack exchange,提问作者MTH
相关产品推荐
相关产品推荐

