【问题标题】:Jq - add a key/value to one JSON file if such key/value exists in another JSON fileJq - 如果键/值存在于另一个 JSON 文件中,则将键/值添加到一个 JSON 文件
【发布时间】:2026-01-24 15:00:02
【问题描述】:

有一个 JSON 文件 - landline.json

[
    {
        "City": "San Francisco",
        "Person": "John Doe",
        "Landline": false
    },
    {
        "City": "Los Angeles",
        "Person": "Steve Smith",
        "Landline": false
    }
]

还有另一个 JSON 文件 - mobile.json

[
    {
        "City": "San Francisco",
        "Person": "John Doe",
        "Mobile": false
    },
    {
        "City": "Los Angeles",
        "Person": "Jenny Miller",
        "Mobile": false
    }
]

问题是如何使用 jq 的过滤器和条件语句在"Landline": false "Mobile": false 之后为John Doe 创建一个新文件/数组?所以生成的数组应该如下所示:

[
    {
        "City": "San Francisco",
        "Person": "John Doe",
        "Landline": false,
        "Mobile": false
    },
    {
        "City": "Los Angeles",
        "Person": "Steve Smith",
        "Landline": false
    }
]

所以算法应该遵循 - 如果在 mobile.json 中有 "Person": "John Doe" 条目并且在同一个块中有 "Mobile": false 条目,则在 "Landline": false 之后添加 "Mobile": false 条目以用于 @ 中的 "Person": "John Doe" 987654333@.

【问题讨论】:

  • 你自己努力了吗?
  • 那么,MobileLandline 是两个文件之间唯一不同的键吗?
  • @oguzismail 是的,Mobile 和 Landline 是唯一不同的键。可能还值得一提的是,在每个文件中,“Person”的值是唯一的。换句话说 - 在旧金山、洛杉矶或其他城市,您将只有一个“Jon Doe”。
  • 那你也可以用jq -s 'add | group_by(.Person) | map(add | select(has("Landline") and (.Mobile | not)))' landline.json mobile.json

标签: arrays json if-statement search jq


【解决方案1】:

这里有一个过滤器可以帮助您入门。在 merge.jq 和您指定的其他文件中包含以下内容

def key: [.Person, .City] ;
[
      reduce .[][] as $e ({}; setpath($e|key; getpath($e|key) + $e)) 
    | .[][]
    | select(.Landline != null)
]

命令

jq -Ms -f merge.jq landline.json mobile.json 

生产

[
  {
    "City": "San Francisco",
    "Person": "John Doe",
    "Landline": false,
    "Mobile": false
  },
  {
    "City": "Los Angeles",
    "Person": "Steve Smith",
    "Landline": false
  }
]

要了解这里发生了什么,请观察这个过滤器是如何工作的

def key: [.Person, .City] ;
reduce .[][] as $e ({}; setpath($e|key; getpath($e|key) + $e)) 

构造一个临时嵌套对象,其键是来自输入的 Person 和 City

{
  "John Doe": {
    "San Francisco": {
      "City": "San Francisco",
      "Person": "John Doe",
      "Landline": false,
      "Mobile": false
    }
  },
  "Steve Smith": {
    "Los Angeles": {
      "City": "Los Angeles",
      "Person": "Steve Smith",
      "Landline": false
    }
  },
  "Jenny Miller": {
    "Los Angeles": {
      "City": "Los Angeles",
      "Person": "Jenny Miller",
      "Mobile": false
    }
  }
}

从此对象迭代和选择用于转换回所需的形式,仅保留具有非空 Landline 的对象。

【讨论】:

  • 完美!你知道吗 - 临时数组可能是一个更好的解决方案。相关问题 - 您的解决方案可以扩展以包含其他密钥吗?比如如果有一个额外的文件 car.json 里面有"car": false 附加键?
  • 在上面回答我自己的评论 - 是的,只需要运行上述过滤器两次 - 一次获得中间结果,然后使用 car.json 文件获得最终结果,该结果将具有 Mobile, @ 987654328@ 和 Car 键。再次感谢
【解决方案2】:

对于这类问题,“字典查找”很容易理解,并且给出了jq的INDEX函数,也很容易实现。例如:

jq -n ' 
  def key: {City,Person};
  (input | INDEX(.[]; key) | map_values( {Mobile} ) ) as $mobile
  | input | map( . + $mobile[key|tostring] )
' mobile.json landline.json

【讨论】:

    最近更新 更多