JQ денормализовать вложенное поле - PullRequest
2 голосов
/ 26 февраля 2020

отказ от ответственности: действительно, уже есть разные ответы (например, JQ Присоединяет JSON файлов по ключу или денормализует JSON с помощью jq ), но ни один из них мне помогли или у меня были другие обстоятельства, из которых я не смог найти решение; /


У меня есть 2 файла, оба являются списками объектов, в одном из которых есть ссылки на поля для идентификаторов объектов другого

учитывая

[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1"
    }
  }
]

и

[
  {
    "id": "5de82d5072f4a72ad5d5dcc1",
    "name": "FooBar"
  }
]

моя цель - получить денормализованный список объектов:

ожидается

[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1",
      "name": "FooBar"
    }
  }
]

, хотя я могу выполнять основные части, я еще не ставил задачу объединить оба:

с пример 1

jq -s '(.[1][] | select(.id == "5de82d5072f4a72ad5d5dcc1"))' objects.json referredObjects.json

я получаю

{
  "id": "5de82d5072f4a72ad5d5dcc1",
  "name": "FooBar"
}

и с пример 2

jq -s '.[0][] | .reference = {}' objects.json referredObjects.json

могу манипулировать любым .reference получением

{
  "id": "5b9f50ccdcdf200283f29052",
  "reference": {}
}

(даже если я потеряю структуру списка)

Но: я не могу сделать s.th. как

выполняется "соединение"

jq -s '.[0][] as $obj | $obj.reference = (.[1][] | select(.id == $obj.reference.id))' objects.json referredObjects.json

даже подходит с foreach или reduce выглядит многообещающе

jq -s '[foreach .[0][] as $obj ({}; .reference.id = ""; . + $obj )]' objects.json referredObjects.json

=>

[
  {
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1"
    },
    "id": "5b9f50ccdcdf200283f29052"
  }
]

, где я ожидал получить то же, что и во втором примере

В итоге у меня начались головные боли, и я с нетерпением жду возможности написать неэффективную рутину на любом языке ... надеюсь, я был бы признателен любому помощь по этому вопросу

~ Марсель

Ответы [ 2 ]

3 голосов
/ 26 февраля 2020

Преобразуйте второй файл в объект, в котором идентификаторы и имена связаны, и используйте его в качестве ссылки при обновлении первого файла.

$ jq '(map({(.id): .}) | add) as $idx
      | input
      | map_values(.reference = $idx[.reference.id])' file2 file1
[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1",
      "name": "FooBar"
    }
  }
]
2 голосов
/ 26 февраля 2020

Следующее решение использует ту же стратегию, которая использовалась в решении @OguzIsmail, но использует встроенную функцию INDEX/2 для построения словаря из второго файла.

Важным моментом является то, что эта стратегия позволяет массивам в обоих файлах иметь произвольный размер.

Вызов

jq --argfile file2 file2.json -f program.jq file1.json

program.jq

INDEX($file2[]; .id) as $dict
| map(.reference.id as $id | .reference = $dict[$id])
...