如何在每个对象都有Name属性的嵌套JSON上使用JQ递归? [英] How to recurse with jq on nested JSON where each object has a name property?

查看:35
本文介绍了如何在每个对象都有Name属性的嵌套JSON上使用JQ递归?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌套的JSON对象,其中每个级别都有相同的属性键,每个级别的区别是一个名为name的属性。如果我要向下遍历到具有name属性的特定"路径"的级别,我应该如何制定jq过滤?

以下是表示文件系统目录结构的一些示例JSON数据:

{
  "subs": [
    {
      "name": "aaa",
      "subs": [
        {
          "name": "bbb",
          "subs": [
            {
              "name": "ccc",
              "subs": [
                {
                  "name": "ddd",
                  "payload": "xyz"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

获取路径aaa/bbb/ccc/ddd中负载的值的jq过滤是什么?

以前的研究:

  1. jq - select objects with given key name-有帮助,但在JSON中查找包含指定名称的任何元素,而我查找的是嵌套在一组也具有特定名称的对象下的元素。

  2. http://arjanvandergaag.nl/blog/wrestling-json-with-jq.html-在第4节中很有帮助,其中显示了如何提取具有特定值的属性name的对象。但是,执行的递归基于一组特定的已知属性名称("Values[].links.clone[]")。在我的例子中,我的等价物只是"subs[].Subs[].Subs[]"。

推荐答案

以下是通用解决方案的基础:

def descend(name): .subs[] | select(.name == name);

因此您的特定查询可以表示为:

descend( "aaa") | descend( "bbb") | descend( "ccc") | descend( "ddd") | .payload

或稍好一些,仍使用上述descend的定义:

def path(array): 
  if (array|length)==0 then . 
  else descend(array[0]) | path(array[1:])
  end;

path( ["aaa", "bbb", "ccc", "ddd"] ) | .payload

总拥有成本

上述path/1的递归定义非常简单,但不适合嵌套非常深的数据结构,例如深度大于1000的数据结构。下面是另一个定义,它利用了JQ的尾部调用优化,因此运行速度非常快:

def atpath(array):
  [array, .] 
  |  until( .[0] == []; .[0] as $a | .[1] | descend($a[0]) | [$a[1:], . ] )
  | .[1];

.aaa.bbb.ccc.ddd

如果您希望能够使用.aaa.bbb.ccc.ddd表示法,一种方法是从"展平"数据开始:

def flat:
  { (.name): (if .subs then (.subs[] | flat) else .payload end) };

由于顶级元素没有"name"标记,因此查询将为:

.subs[] | flat | .aaa.bbb.ccc.ddd

这里有一个更有效的方法,再次使用上面定义的descend

def payload(p):
  def get($array):
    if $array == []
    then .payload
    else descend($array[0]) | get($array[1:]) end;
  get( null | path(p) );

payload( .aaa.bbb.ccc.ddd )

这篇关于如何在每个对象都有Name属性的嵌套JSON上使用JQ递归?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆