【问题标题】:jq - How do I print a parent value of an object when I am already deep into the object's children?jq - 当我已经深入到对象的子对象中时,如何打印对象的父值?
【发布时间】:2016-12-05 23:46:37
【问题描述】:

假设我有以下 JSON,存储在我的变量 jsonVariable 中。

{
    "id": 1,
    "details": {
        "username": "jamesbrown",
        "name": "James Brown"
    }
}

我用 jq 解析这个 JSON:

echo $jsonVariable | jq '.details.name | select(.name == "James Brown")'

这会给我输出

詹姆斯·布朗

但是如果我也想得到这个人的 id 怎么办?现在,我知道这是一个粗略而简单的例子——我目前正在使用的程序有 5 或 6 层深,除了 select 之外还有许多不同的 JQ 函数。在执行各种过滤方法后,当我已经 5 或 6 层深时,我需要一种方法来选择父字段。

有人可以帮忙吗?有没有办法“逆向”,回到父母那里? (不确定我是否有道理!)

【问题讨论】:

  • 好像你想要.id | select(.name == "James Brown")你试过了吗?
  • 抱歉,没有正确解释。我希望两者都有
  • 你可以像. | select(.details | .name == ("James Brown", "Elon Musk")) | .id那样做

标签: json jq


【解决方案1】:

对于更通用的方法,将“父”元素的值保存在所需的详细信息级别,然后在过滤器的末尾通过管道传递:

jq '. as $parent | .details.name | select(. == "James Brown") | $parent'

当然,对于您公开的琐碎案例,您可以完全省略:

jq 'select(.details.name == "James Brown")'

另外,请考虑如果您的选择过滤器为单个父对象返回多个匹配项,您将收到每个匹配项的父对象副本。您可能希望通过将父级别以下的所有匹配项包装到一个数组中来确保您的选择过滤器仅返回父级别的一个元素,或者使用unique 对最终结果进行重复数据删除。

【讨论】:

  • 很好的解决方案。但是你为什么说“你会收到每场比赛的父对象的副本”? $parent 变量(或更一般地我们可以称之为 $ancestor)应该被绑定一次,然后当你沿着树向下遍历任何数组时,在那个祖先下,你总是会得到第一次绑定到的相同对象变量,没有“复制”。即使是这样,为什么有人会在意?只要我能掌握我感兴趣的祖先,我应该没问题,不是吗?
  • 如果您正在修改对象而不是仅仅阅读它,“复制”部分很重要。修改将发生在副本上,但将 $parent 传递到末尾只会设置 .到原始的、未修改的对象。或者换一种说法,如果你想在修改孩子之后返回父母,这个接受的答案将不起作用。
【解决方案2】:

试一试:

echo $jsonVariable | jq '{Name: .details.name, Id: .Id}  | select(.name == "James Brown")'

【讨论】:

    【解决方案3】:

    而不是查询到您正在测试的值,而是查询到包含您正在查询的值和您希望选择的值的根对象。

    您需要包含idname 的对象。

    $ jq --arg name 'James Brown' 'select(.details.name == $name).id' input.json
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-03
      • 2013-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      相关资源
      最近更新 更多