【问题标题】:jq denormalize a nested fieldjq非规范化嵌套字段
【发布时间】:2020-02-26 11:45:41
【问题描述】:

免责声明:确实,已经有不同的答案(如JQ Join JSON files by keydenormalizing JSON with jq),但它们都没有帮助我,或者确实有不同的情况,我无法从中得出解决方案;/ em>


我有 2 个文件,它们都是对象列表,其中一个具有对另一个对象 ID 的字段引用

给定

[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1"
    }
  }
]

[
  {
    "id": "5de82d5072f4a72ad5d5dcc1",
    "name": "FooBar"
  }
]

我的目标是获得一个非规范化的对象列表:

预期

[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1",
      "name": "FooBar"
    }
  }
]

虽然我能够完成主要部分,但我还没有挑战将两者结合在一起:

示例 1

jq -s '(.[1][] | select(.id == "5de82d5072f4a72ad5d5dcc1"))' objects.json referredObjects.json

我明白了

{
  "id": "5de82d5072f4a72ad5d5dcc1",
  "name": "FooBar"
}

并与 示例 2

jq -s '.[0][] | .reference = {}' objects.json referredObjects.json

我可以操纵任何.reference 获取

{
  "id": "5b9f50ccdcdf200283f29052",
  "reference": {}
}

(即使我失去了列表结构)

但是:我不能做某事。喜欢

执行“加入”

jq -s '.[0][] as $obj | $obj.reference = (.[1][] | select(.id == $obj.reference.id))' objects.json referredObjects.json

即使使用 foreachreduce 的方法看起来很有希望

jq -s '[foreach .[0][] as $obj ({}; .reference.id = ""; . + $obj )]' objects.json referredObjects.json

=>

[
  {
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1"
    },
    "id": "5b9f50ccdcdf200283f29052"
  }
]

我希望得到与第二个示例相同的地方

我最终感到头疼,并期待用任何语言写一个无效的例行程序......希望我能在这方面得到任何帮助

~马塞尔

【问题讨论】:

    标签: json jq


    【解决方案1】:

    将第二个文件转换为 id 和名称配对的对象,并在更新第一个文件时将其用作参考。

    $ jq '(map({(.id): .}) | add) as $idx
          | input
          | map_values(.reference = $idx[.reference.id])' file2 file1
    [
      {
        "id": "5b9f50ccdcdf200283f29052",
        "reference": {
          "id": "5de82d5072f4a72ad5d5dcc1",
          "name": "FooBar"
        }
      }
    ]
    

    【讨论】:

    • 非常感谢@Oguz-Ismail,如果字段多于 .name,我只是将其简化一次以替换完整的 .reference 对象
    【解决方案2】:

    以下解决方案使用与@OguzIsmail 解决方案相同的策略,但使用内置函数INDEX/2 从第二个文件构造字典。

    重要的一点是,这种策略允许两个文件中的数组为任意大小。

    调用

    jq --argfile file2 file2.json -f program.jq file1.json
    

    program.jq

    INDEX($file2[]; .id) as $dict
    | map(.reference.id as $id | .reference = $dict[$id])
    

    【讨论】:

    • 非常感谢@peak,如果字段多于 .name,我只是简化了一次以替换完整的 .reference 对象另外:不使用 --argfile 的已知限制是什么?从文档中,我希望这会导致更多的内存消耗,在之前的处理中一次读取所有内容 + 文档对 --argfile 说:Do not use. Use --slurpfile instead. 但它不是 1:1 可替换的,不是吗?!
    • 两个命令行选项的语义不同。如果您对使用 --argfile 感到不舒服,请务必使用 --slurpfile(对 jq 过滤器进行必要的微调),或者您也可以使用@OguzIsmail 的答案中的技术。
    • 我不只是不舒服,但我不明白区别以及为什么 --argfile 更健壮,只是问;)
    猜你喜欢
    • 2020-05-06
    • 1970-01-01
    • 2017-12-23
    • 2016-11-15
    • 2017-10-27
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 2020-12-20
    相关资源
    最近更新 更多