【问题标题】:jq: How to combine disjoint object values as a single object of key/value pairs?jq:如何将不相交的对象值组合为键/值对的单个对象?
【发布时间】:2018-03-30 10:57:15
【问题描述】:

如果我有 JSON 输入数据:

input.json

{
   "metadata": {
      "guid": "07f90eed-105d-41b2-bc20-4c20dfb51653"
   },
   "entity": {
      "name": "first"
   }
}
{
   "metadata": {
      "guid": "da187e3a-8db9-49fd-8c05-41f29cf87f51"
   },
   "entity": {
      "name": "second"
   }
}
{
   "metadata": {
      "guid": "6685c3af-5427-4add-8764-7b18ae3c23bb"
   },
   "entity": {
      "name": "third"
   }
}

我想从中创建以下内容:

{
  "first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
  "second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
  "third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}

也就是说,输入数据是一个单独的 JSON 对象的集合,每个对象都有所示的结构。我希望输出是单个 JSON 对象,其中键是 .entity.name,值是 .metadata.guid

我试过了:

jq -r '{.entity.name: .metadata.guid}' input.json
jq -r 'map({(.entity.name): .metadata.guid})' input.json

但这些只会产生语法错误。我得到的最接近的是:

jq -r '.entity.name as $name|.metadata.guid as $guid | { ($name) : ($guid) }' input.json
{
  "first": "07f90eed-105d-41b2-bc20-4c20dfb51653"
}
{
  "second": "da187e3a-8db9-49fd-8c05-41f29cf87f51"
}
{
  "third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}

但是,仍然有 3 个对象(不是 1 个)。

我确实得到了一个表格来给我想要的东西,但我怀疑有一种更简单的方法来做到这一点:

jq -r '.entity.name as $name|.metadata.guid as $guid | { ($name) : ($guid) }' input.json | jq -s add
{
  "first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
  "second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
  "third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}

任何想法如何正确地做到这一点?

【问题讨论】:

  • 不应该是一个对象数组吗?看起来像无效的 JSON
  • jq 可以很好地处理不相交的对象。它不是单个 JSON 对象/数组/字符串等,但 jq 并不要求它只对单个实体进行操作。
  • 获取三个对象的更简单方法是jq '{(.entity.name): .metadata.guid}' input.json。将 .entity.name 包装到括号中告诉 jq 将其作为表达式而不是字符串进行计算。

标签: json jq


【解决方案1】:

使用单个 jq 命令:

jq -s '[.[] | { (.entity.name): .metadata.guid }] | add' input.json
  • -s (--slurp) - 不要为输入中的每个 JSON 对象运行过滤器,而是将整个输入流读入一个大数组并只运行一次过滤器。

输出:

{
  "first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
  "second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
  "third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}

【讨论】:

    【解决方案2】:

    获取三个对象的更简单方法是jq '{(.entity.name): .metadata.guid}' input.json

    将密钥 (.entity.name) 括在括号中告诉 jqevaluate it as an expression,而不是作为字符串。

    这会导致您已经拥有的更简单的形式(使用jq 的两次调用):

    $ jq '{(.entity.name): .metadata.guid}' input.json | jq -s add
    {
      "first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
      "second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
      "third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
    }
    

    【讨论】:

    • 这具有推迟“啜饮”的潜在内存节省优点。
    猜你喜欢
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2017-04-12
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    相关资源
    最近更新 更多