在单个键上合并同一阵列中的对象

时间:2019-12-03 05:45:08

标签: json jq

我有一个JSON对象数组,其格式如下:

[
  {
    "id": 1,
    "names": [
      {
        "name": "Bulbasaur",
        "language": {
          "name": "en",
          "url": "http://myserver.com:8000/api/v2/language/9/"
        }
      },
    ],
  },
  {
    "id": 1,
    "types": [
      {
        "slot": 1,
        "type": {
          "name": "grass",
          "url": "http://myserver.com:8000/api/v2/type/12/"
        }
      },
      {
        "slot": 2,
        "type": {
          "name": "poison",
          "url": "http://myserver.com:8000/api/v2/type/4/"
        }
      }
    ]
  },
  {
    "id": 2,
    "names": [
      {
        "name": "Ivysaur",
        "language": {
          "name": "en",
          "url": "http://myserver.com:8000/api/v2/language/9/"
        }
      },
    ],
  },
  {
    "id": 2,
    "types": [
      {
        "slot": 1,
        "type": {
          "name": "ice",
          "url": "http://myserver.com:8000/api/v2/type/10/"
        }
      },
      {
        "slot": 2,
        "type": {
          "name": "electric",
          "url": "http://myserver.com:8000/api/v2/type/8/"
        }
      }
    ]
  },
  {
    "id": 3,
    "names": [
      {
        "name": "Venusaur",
        "language": {
          "name": "en",
          "url": "http://myserver.com:8000/api/v2/language/9/"
        }
      },
    ],
  },
  {
    "id": 3,
    "types": [
      {
        "slot": 1,
        "type": {
          "name": "ground",
          "url": "http://myserver.com:8000/api/v2/type/2/"
        }
      },
      {
        "slot": 2,
        "type": {
          "name": "rock",
          "url": "http://myserver.com:8000/api/v2/type/3/"
        }
      }
    ]
  }
]

请注意,这些是成对的分离对象,它们按顺序出现在JSON数组中,每对共享一个id字段。此模式在数组中重复数百次。我需要完成的是将每个id共享对“合并”到一个对象中。因此,结果输出将是

[
  {
    "id": 1,
    "names": [
      {
        "name": "Bulbasaur",
        "language": {
          "name": "en",
          "url": "http://myserver.com:8000/api/v2/language/9/"
        }
      },
    ],
    "types": [
      {
        "slot": 1,
        "type": {
          "name": "grass",
          "url": "http://myserver.com:8000/api/v2/type/12/"
        }
      },
      {
        "slot": 2,
        "type": {
          "name": "poison",
          "url": "http://myserver.com:8000/api/v2/type/4/"
        }
      }
    ]
  },
  {
    "id": 2,
    "names": [
      {
        "name": "Ivysaur",
        "language": {
          "name": "en",
          "url": "http://myserver.com:8000/api/v2/language/9/"
        }
      },
    ],
    "types": [
      {
        "slot": 1,
        "type": {
          "name": "ice",
          "url": "http://myserver.com:8000/api/v2/type/10/"
        }
      },
      {
        "slot": 2,
        "type": {
          "name": "electric",
          "url": "http://myserver.com:8000/api/v2/type/8/"
        }
      }
    ]
  },
  {
    "id": 3,
    "names": [
      {
        "name": "Venusaur",
        "language": {
          "name": "en",
          "url": "http://myserver.com:8000/api/v2/language/9/"
        }
      },
    ],
    "types": [
      {
        "slot": 1,
        "type": {
          "name": "ground",
          "url": "http://myserver.com:8000/api/v2/type/2/"
        }
      },
      {
        "slot": 2,
        "type": {
          "name": "rock",
          "url": "http://myserver.com:8000/api/v2/type/3/"
        }
      }
    ]
  }
]

我已经通过group_by(.id)命令使这些对象彼此并排出现,但是我对如何实际组合它们感到困惑。我仍然是jq的新手,所以我对可能的解决方案不知所措。

1 个答案:

答案 0 :(得分:2)

[注意:以下假设Q中显示的数据已更正,因此它们是有效的JSON。]

所需的合并可以通过对象添加(x + y)来实现。例如,给定问题中所示的两个JSON对象(即作为流),您可以编写:

jq -s '.[0] + .[1]'

但是,由于该问题还表明这些对象实际上位于数组中,因此让我们接下来考虑具有两个对象的数组的情况。在这种情况下,您只需写:

jq add

最后,如果您有一个数组数组,每个数组都是对象数组,则可以使用map(add)。由于您没有非常大的数组,因此可以简单地编写:

group_by(.id) | map(add)

请注意,jq以非交换方式定义对象添加。具体来说,偏向最右边的键。