使用JQ将复杂的JSON文件转换为简单的JSON文件,而无需获得笛卡尔积

时间:2018-07-02 13:47:52

标签: json jq

我想使用JQ将复杂的JSON文件转换为简单的JSON文件。但是,我正在使用的查询生成了错误的输出。

我的(缩减的)JSON文件:

[
  {
    "id": 100,
    "foo": [
      {
        "bar": [
          {"type": "read"},
          {"type": "write"}
        ],
        "users": ["admin_1"],
        "groups": []
      },
      {
        "bar": [
          {"type": "execute"},
          { "type": "read"}
        ],
        "users": [],
        "groups": ["admin_2"]
      }
    ]
  },
  {
    "id": 101,
    "foo": [
      {
        "bar": [
          {"type": "read"}
        ],
        "users": [
          "admin_3"
        ],
        "groups": []
      }
    ]
  }
]

我需要生成一个更扁平的JSON文件,并将用户和组合并到一个字段中,类似于此:

 [
  {
    "id": 100,
    "users_groups": [
      "admin_1",
      "admin_2"
    ],
    "bar": ["read"]
  },
  {
    "id": 100,
    "users_groups": ["admin_1"],
    "bar": ["write"]
  },
  {
    "id": 100,
    "users_groups": ["admin_2"],
    "bar": ["execute"]
  },
   {
    "id": 101,
    "users_groups": ["admin_3"],
    "bar": ["read"]
  }
 ]  

我在JQ中尝试的所有操作都会导致输出错误(其中admin_1错误地具有bar = execute,而admin_2错误地具有bar = write),类似于以下内容:

[
  {
    "id": 100,
    "users_groups": [
      "admin_1",
      "admin_2"
    ],
    "bar": ["read", "write", "execute"]
  },
   {
    "id": 101,
    "users_groups": ["admin_3"],
    "bar": ["read"]
  }
 ] 

我已经尝试过许多此类查询-知道我应该怎么做吗?

    cat file.json | jq -r '[.[] | select(has("foo")) |{"id", "users":(.foo[] | .users), "groups":(.foo[] | .groups), "bar":([.foo[].bar[] | .type])} ] '

1 个答案:

答案 0 :(得分:1)

以下问题似乎按要求按“类型”对以下过滤器进行了分组:

map(.id as $id
    | [.foo[]
      | {id: $id, bar: .bar[].type} +
        {"users_groups": (.users + .groups)[]} ]
    | group_by(.bar)
    | map(.[0] + {"users_groups": [.[].users_groups]}) )

输出

[
  [
    {
      "id": 100,
      "bar": "execute",
      "users_groups": [
        "admin_2"
      ]
    },
    {
      "id": 100,
      "bar": "read",
      "users_groups": [
        "admin_1",
        "admin_2"
      ]
    },
    {
      "id": 100,
      "bar": "write",
      "users_groups": [
        "admin_1"
      ]
    }
  ],
  [
    {
      "id": 101,
      "bar": "read",
      "users_groups": [
        "admin_3"
      ]
    }
  ]
]

变化

要获得对象数组的输出格式,只需添加| [.[][]]即可; 同样,确保.bar是数组值也很容易,尽管考虑到按.type进行分组,这可能毫无意义。