代码之家  ›  专栏  ›  技术社区  ›  Александр Королёв

如何在jq中的嵌套对象中获取父对象键?

  •  0
  • Александр Королёв  · 技术社区  · 6 年前

    我有带嵌套对象的JSON

    {
     "schema1": {
        "table1": {
            "status": 0
        },
        "table2": {
            "status": 1
        }
     },
     "schema2": {
        "table1": {
            "status": 0
        },
        "table2": {
            "status": 1
        }
     }
    }
    

    我需要在模式列表中。按状态==1筛选的表。 我的第一个方法是

    .[]|.[]|(select(.status==1))|"table.schema  \(.status)"
    

    如何替换表格。具有父对象的适当键的架构?

    Here is jq play with example

    预期结果是:

    [ "schema1.table2", "schema2.table2" ]
    
    5 回复  |  直到 6 年前
        1
  •  3
  •   Александр Королёв    6 年前

    我选择了这样的解决方案

    path(.[]|.[]|select(.status==1))|join(".")
    
        2
  •  0
  •   peak    6 年前

    如果输入文档太大,无法在内存中轻松容纳,那么使用jq的流解析器的解决方案将是合适的。

    为此,请考虑程序。jq如下:

    select(length==2 and .[-1] == 1 and .[0][-1] == "status")
    | .[0][:-1]
    | join(".")
    

    (此处 [:-1] 是一种简洁的写作方式 [0:-1] ,它实际上只接受数组中的最后一个项目。)

    调用: jq --stream -f program.jq input.json

    将生成流:

    "schema1.table2"
    "schema2.table2"
    

    如果需要一个值数组,可以将此流通过管道传输到 jq -s .

    请注意该程序。如上所述的jq实际上解决了嵌套可以任意深度的一般问题。

        3
  •  0
  •   RomanPerekhrest    6 年前

    jq 解决方案:

    jq -r '. as $o | paths 
           | select(length == 3) 
           | select($o[.[0]][.[1]][.[2]] == 1) 
           | .[0] +"."+ .[1]' file.json
    

    输出:

    schema1.table2
    schema2.table2
    
        4
  •  0
  •   peak    6 年前

    以下用途 to_entries (两次)按要求生成阵列:

    [to_entries[]
     |  .key as $k
     | .value | to_entries | map(select(.value.status == 1))[]
     | [$k, .key]
     | join(".") ]
    
        5
  •  0
  •   Jeff Mercado    6 年前

    在这种情况下,您可以使用 paths(scalars) (以前 leaf_paths )获取所有标量值的路径。通过这些路径,您可以使用 getpath/1 获取值并输出所需字符串。

    paths(scalars) as $p
      | select($p[-1] == "status" and getpath($p) == 1)
      | "\([$p[1,0]] | join(".")) \(getpath($p))"
    

    如果您想获得更多乐趣,还可以使用流一次性获得路径和值。

    tostream as [$p,$v]
      | select($p[-1] == "status" and $v == 1)
      | "\([$p[1,0]] | join(".")) \($v)"
    

    但考虑到您的评论,如果您只需要路径,可以将其归结为:

    [tostream as [$p,$v]
      | select($p[-1] == "status" and $v == 1)
      | $p[:2] | join(".")
    ]