26

我正在考虑以下 JSON 对象数组:

[
  {
    "index": "index1",
    "type": "type1",
    "id": "id1",
    "fields": {
      "deviceOs": [
        "Android"
      ],
      "deviceID": [
        "deviceID1"
      ],
      "type": [
        "type"
      ],
      "country": [
        "DE"
      ]
    }
  },
  {
    "index": "index2",
    "type": "type2",
    "id": "id2",
    "fields": {
      "deviceOs": [
        "Android"
      ],
      "deviceID": [
        "deviceID2"
      ],
      "type": [
        "type"
      ],
      "country": [
        "US"
      ]
    }
  }
]

我想把它展平以获得:

[
  {
    "index": "index1",
    "type": "type",
    "id": "id1",
    "deviceOs": "Android",
    "deviceID": "deviceID1",
    "country": "DE"
  },
  {
    "index": "index2",
    "type": "type",
    "id": "id2",
    "deviceOs": "Android",
    "deviceID": "deviceID2",
    "country": "US"
  }
]

我正在尝试使用,jq但我无法将"fields". 我该怎么做?目前我对命令行工具很感兴趣,但我也愿意接受其他建议。

4

5 回答 5

41

这是一个很难制作的。

map
(
    with_entries(select(.key != "fields"))
    +
    (.fields | with_entries(.value = .value[0]))
)

让我们把它分解并解释它的部分

  1. 对于数组中的每个项目...

    map(...)
    
  2. 创建一个新对象,其中包含除fields属性之外的所有值。

    with_entries(select(.key != "fields"))
    
  3. 将其与...结合起来

    +
    
  4. 每个将fields每个值投影到每个数组的第一项

    (.fields | with_entries(.value = .value[0]))
    
于 2014-07-12T06:32:45.063 回答
9

有一个名为的工具gron,您可以通过管道输入该 json,以获得类似的东西。

$ gron document.json
json = [];
json[0] = {};
json[0].fields = {};
json[0].fields.country = [];
json[0].fields.country[0] = "DE";
json[0].fields.deviceID = [];
json[0].fields.deviceID[0] = "deviceID1";
json[0].fields.deviceOs = [];
json[0].fields.deviceOs[0] = "Android";
json[0].fields.type = [];
json[0].fields.type[0] = "type";
json[0].id = "id1";
json[0].index = "index1";
json[0].type = "type1";
json[1] = {};
json[1].fields = {};
json[1].fields.country = [];
json[1].fields.country[0] = "US";
json[1].fields.deviceID = [];
json[1].fields.deviceID[0] = "deviceID2";
json[1].fields.deviceOs = [];
json[1].fields.deviceOs[0] = "Android";
json[1].fields.type = [];
json[1].fields.type[0] = "type";
json[1].id = "id2";
json[1].index = "index2";
json[1].type = "type2";

于 2019-02-09T02:45:32.187 回答
8

您可以使用此过滤器:

[.[] | {index: .index, type: .type, id: .id, deviceOs: .fields.deviceOs[],deviceID: .fields.deviceID[],country: .fields.country[]}]

你可以在这里测试https://jqplay.org

于 2014-08-30T19:17:37.760 回答
4

以下是一些变体,首先将 .fields 合并到包含对象中,然后使用 + 展平数组元素。首先我们处理 .fields

  .[]
| . + .fields
| del(.fields)

这给我们留下了看起来像的物体

{
  "index": "index1",
  "type": [
    "type"
  ],
  "id": "id1",
  "deviceOs": [
    "Android"
  ],
  "deviceID": [
    "deviceID1"
  ],
  "country": [
    "DE"
  ]
}

然后我们可以通过多种方式展平键。一种方法是使用with_entries

| with_entries( .value = if .value|type == "array" then .value[0] else .value end )

另一种方法是使用reducesetpath

| . as $v
| reduce keys[] as $k (
    {};
    setpath([$k]; if $v[$k]|type != "array" then $v[$k] else $v[$k][0] end)
  )
于 2017-08-02T17:05:26.717 回答
1

类似于@jq170727 anwser:

jq 'map(. + (.fields | with_entries(.value |= .[])) | del(.fields))'

(假设内部没有字段.fields本身称为.fields)。

|with_entries(.value|=.[])部分是将值数组展平-.fields请注意仅保留第一项。.value|=join(", ")可用于将多个字符串值合并为一个。

于 2021-09-21T15:16:04.993 回答