JQ获取嵌套数组的错误输出

时间:2018-06-26 21:40:02

标签: json jq

我正在尝试使用JQ将json文件转换为csv文件。我已经设法对文件执行此操作,但是在测试过程中,我发现输出与预期不符。请帮忙,因为我花了数小时尝试修复它,但似乎无法达到目标。

理想情况下,我也想将用户和组合并为一个,但是我可以没有它。

这是我的json文件的简化版本。

[
  {
    "id": 319,
    "policyItems": [
      {
        "accesses": [
          {
            "type": "consume",
            "isAllowed": true
          },
          {
            "type": "create",
            "isAllowed": true
          }
        ],
        "users": [
          "foo"
        ],
        "groups": []
      },
      {
        "accesses": [
          {
            "type": "publish",
            "isAllowed": true
          },
          {
            "type": "create",
            "isAllowed": true
          }
        ],
        "users": [],
        "groups": [
          "bar"
        ]
      }
    ]
  },
  {
    "id": 320,
    "policyItems": [
      {
        "accesses": [
          {
            "type": "publish",
            "isAllowed": true
          },
          {
            "type": "create",
            "isAllowed": true
          }
        ],
        "users": [
          "foo"
        ],
        "groups": []
      },
      {
        "accesses": [
          {
            "type": "consume",
            "isAllowed": true
          },
          {
            "type": "create",
            "isAllowed": true
          }
        ],
        "users": [],
        "groups": [
          "bar"
        ]
      }
    ]
    }
]

我尝试了此JQ代码的各种版本,但对于id = 319,user = foo应该具有使用权和创建权,而group = bar应该具有发布和创建权。但是我总是以foo和bar最终都可以使用,发布和创建访问权限(或其他错误)。

我尝试过:

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

输出:

      [
      {
        "id": 319,
        "users": [
          "foo"
        ],
        "groups": [],
        "access_type": [
          "consume",
          "create",
          "publish",
          "create"
        ]
      },
      {
        "id": 319,
        "users": [
          "foo"
        ],
        "groups": [
          "bar"
        ],
        "access_type": [
          "consume",
          "create",
          "publish",
          "create"
        ]
      },
      {
        "id": 319,
        "users": [],
        "groups": [],
        "access_type": [
          "consume",
          "create",
          "publish",
          "create"
        ]
      },
      {
        "id": 319,
        "users": [],
        "groups": [
          "bar"
        ],
        "access_type": [
          "consume",
          "create",
          "publish",
          "create"
        ]
      },
      {
        "id": 320,
        "users": [
          "foo"
        ],
        "groups": [],
        "access_type": [
          "publish",
          "create",
          "consume",
          "create"
        ]
      },
      {
        "id": 320,
        "users": [
          "foo"
        ],
        "groups": [
          "bar"
        ],
        "access_type": [
          "publish",
          "create",
          "consume",
          "create"
        ]
      },
      {
        "id": 320,
        "users": [],
        "groups": [],
        "access_type": [
          "publish",
          "create",
          "consume",
          "create"
        ]
      },
      {
        "id": 320,
        "users": [],
        "groups": [
          "bar"
        ],
        "access_type": [
          "publish",
          "create",
          "consume",
          "create"
        ]
      }
      ]

我也尝试过:

cat file.json | jq  ' map({id, "access_type":([.policyItems[].accesses[] | .type])[], "users":(.policyItems[] | .users)[], "groups":(.policyItems[] | .groups)}) '

哪个提供输出:

    [
{
    "id": 319,
    "access_type": "consume",
    "users": "foo",
    "groups": []
  },
  {
    "id": 319,
    "access_type": "consume",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 319,
    "access_type": "create",
    "users": "foo",
    "groups": []
  },
  {
    "id": 319,
    "access_type": "create",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 319,
    "access_type": "publish",
    "users": "foo",
    "groups": []
  },
  {
    "id": 319,
    "access_type": "publish",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 319,
    "access_type": "create",
    "users": "foo",
    "groups": []
  },
  {
    "id": 319,
    "access_type": "create",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 320,
    "access_type": "publish",
    "users": "foo",
    "groups": []
  },
  {
    "id": 320,
    "access_type": "publish",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 320,
    "access_type": "create",
    "users": "foo",
    "groups": []
  },
  {
    "id": 320,
    "access_type": "create",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 320,
    "access_type": "consume",
    "users": "foo",
    "groups": []
  },
  {
    "id": 320,
    "access_type": "consume",
    "users": "foo",
    "groups": [
      "public"
    ]
  },
  {
    "id": 320,
    "access_type": "create",
    "users": "foo",
    "groups": []
  },
  {
    "id": 320,
    "access_type": "create",
    "users": "foo",
    "groups": [
      "public"
    ]
    }
    ]

谢谢。

编辑: 我的预期输出将是这样的,其中用户和组被合并并正确显示正确的访问权限。

  [
  {
    "id": 319,
    "users_groups": [
      "foo",
      "bar"
    ],
    "access_type": [
      "create"
    ]
  },
  {
    "id": 319,
    "users_groups": [
      "foo"
    ],
    "access_type": [
      "consume"
    ]
  },
  {
    "id": 319,
    "users_groups": ["bar"],
    "access_type": [
      "publish"
    ]
  },
  ...

1 个答案:

答案 0 :(得分:0)

我认为您想要这样的东西:

# Print out your top example input
echo '{"id":319,"policyItems":[{"accesses":[{"type":"consume","isAllowed":true},{"type":"create","isAllowed":true}],"users":["foo"],"groups":[]},{"accesses":[{"type":"publish","isAllowed":true},{"type":"create","isAllowed":true}],"users":[],"groups":["bar"]}]}
{"id":320,"policyItems":[{"accesses":[{"type":"publish","isAllowed":true},{"type":"create","isAllowed":true}],"users":["foo"],"groups":[]},{"accesses":[{"type":"consume","isAllowed":true},{"type":"create","isAllowed":true}],"users":[],"groups":["bar"]}]}' \
| jq -n '[inputs | .id as $id | .policyItems[] | {"id": $id, "access_type": (reduce .accesses[].type as $item ([]; . + [$item])), "users_groups": (.users + .groups)}]'

这是正在发生的事情

  • echo '{"id":...我们正在回馈您的意见
  • | jq用管道输送到jq
  • jq -n '[inputs | ...]我们将jq的回显输入作为流过滤器inputs(而不是.)作为流过滤器,以便我们一次处理全部输入,以便将结果包装在外括号中。
    • -n在这里很重要,因为它指示jq不能隐式使用管道输入。
  • .id as $id我们将父ID保存到$id变量中以供将来参考
  • | policyItems[]我们正在遍历policyItems数组,这似乎是您希望对结果进行分组的依据
  • | {"id": $id, ...在这里,我们开始构建结果,并返回到我们保存的$id
  • "access_type": (reduce .accesses[].type as $item ([]; . + [$item])), ...在这里,我们使用reduce过滤器将访问类型组合到单个数组中
  • "users_groups": (.users + .groups)},我们最终将"users""groups"数组合并为一个数组

所有这些使我们能够返回如下输出:

[
  {
    "id": 319,
    "access_type": [
      "consume",
      "create"
    ],
    "users_groups": [
      "foo"
    ]
  },
  {
    "id": 319,
    "access_type": [
      "publish",
      "create"
    ],
    "users_groups": [
      "bar"
    ]
  },
  {
    "id": 320,
    "access_type": [
      "publish",
      "create"
    ],
    "users_groups": [
      "foo"
    ]
  },
  {
    "id": 320,
    "access_type": [
      "consume",
      "create"
    ],
    "users_groups": [
      "bar"
    ]
  }
]