JQ получает неправильный вывод для вложенных массивов - PullRequest
0 голосов
/ 27 июня 2018

Я пытаюсь использовать 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 пользователь = foo должен иметь доступ, использовать и создавать, а группа = бар должен иметь доступ для публикации и создания. Но у меня всегда получается, что и 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"
    ]
    }
    ]

Заранее спасибо.

Edit: Мой ожидаемый результат будет примерно таким, когда пользователи и группы объединяются и правильно показывают правильный доступ.

  [
  {
    "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 голосов
/ 07 ноября 2018

Я думаю, вы хотите что-то вроде этого:

# 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 для дальнейшего использования
  • | 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"
    ]
  }
]
...