首页 > 解决方案 > 在 JQ 中从外部文件中查找 ID

问题描述

我有一个查找文件,将 ID 从一个系统映射到另一个系统:

[
  {
    "idA": 2547,
    "idB": "5d0bf91d191c6554d14572a6"
  },
  {
    "idA": 2549,
    "idB": "5b0473f93d4e53db19f8c249"
  },
  {
    "idA": 2550,
    "idB": "5d0bfabc8f20917b92ff07dc"
  },
...

我有一个数据文件,其中包含来自以下系统之一的值和 ID:

[
  {
    "idB": "5d0bf91d191c6554d14572a6",
    "description": "Description for 5d0bf91d191c6554d14572a6"
  },
  {
    "idB": "5d0bf49e9236c57281811cfc",
    "description": "Description for 5d0bf49e9236c57281811cfc"
  },
  {
    "idB": "5d0bfabc8f20917b92ff07dc",
    "description": "Description for 5d0bfabc8f20917b92ff07dc"
  },
...

我想生成一个新的描述文件,并将它们的 ID 转换为idA查找文件中的值。我试过这个:

jq --slurpfile idmap ids.json 'map( {"description":.description, "id": (.idB as $b|$idmap[][]|select(.idB==$b)|.idA) } )' descriptions.json

但它只产生一个空数组。

我必须双重取消引用$idmap,因为 slurping 文件“将解析的 JSON 值的数组绑定到给定的全局变量”——所以只是这样做$idmap[]会引发错误,jq: error (at descriptions.json:70): Cannot index array with字符串 "idB"

谁能解释我在这里做错了什么?

标签: jsonjq

解决方案


这是对所述问题的简洁明了的解决方案。

为简单起见,我们将首先使用以下方法构造一个包含相关映射的字典INDEX/2

INDEX($idmap[]; .idB) | map_values(.idA)

现在任务很简单:

(INDEX($idmap[]; .idB) | map_values(.idA)) as $dict
| map( {description, "idA": $dict[.idB] } )

这假定使用 --argfile idmap ids.json 的调用来避免由 --slurpfile 引起的不需要的“slurping”,但如果使用后者,那么您将使用$idmap[][]原始问题中所述的代替。

由于示例片段不包含任何匹配的“idB”值,因此显示使用这些片段获得的输出几乎没有意义。

变化

如果其中的对象descriptions.js有其他应该保留的键,那么以下变体可能是更有用的指南:

(INDEX($idmap[]; .idB) | map_values(.idA)) as $dict    # or $idmap[][] as above
| map( .idA = $dict[.idB] | del(.idB) )

推荐阅读