Как создать преобразованные вложенные элементы JSON с помощью jq? - PullRequest
1 голос
/ 10 июля 2019

У меня есть JSON-файл с вложенными элементами, который я пытаюсь манипулировать в неопубликованный JSON-файл. Как мне это сделать?

Используя js, я попытался выделить проценты, что я смог сделать. Я не уверен, как переименовать поле процента. Я видел случаи, когда похоже, что value.gender или value.grade должны работать, но я также не уверен, как их объединить.


jq '.data[] | .id as $id | (.demographics[] | .percentage as $percentage | .gender as $gender | .grade as $grade | {"id":$id, "percentage":$percentage})' test2.json

Отсюда я хочу иметь возможность переименовать поле процента в значения пола и оценок. Затем я хочу сгруппировать по идентификатору.

Вот оригинальный файл JSON (test2.json):


{
   "data": [{
         "id": "abc",
         "students": "elementary",
         "demographics": [{
               "grade": "K-2",
               "percentage": "0.1",
               "gender": "unspecified"
            },
            {
               "grade": "K-2",
               "gender": "male",
               "percentage": "0.5"
            },
            {
               "gender": "female",
               "percentage": "0.4",
               "grade": "K-2"
            },
            {
               "grade": "3-6",
               "percentage": "0.3",
               "gender": "male"
            },
            {
               "percentage": "0.2",
               "gender": "unspecified",
               "grade": "3-6"
            },
            {
               "grade": "3-6",
               "gender": "female",
               "percentage": "0.5"
            }
         ],

         "neighborhood_name": [{
               "percentage": "0.5",
               "neighborhood": "atwood"
            },
            {
               "region": "bluff",
               "percentage": "0.5"
            }
         ]
      },
      {
         "id": "def",
         "students": "midhigh",
         "demographics": [{
               "grade": "7-9",
               "percentage": "0.2",
               "gender": "unspecified"
            },
            {
               "grade": "7-9",
               "gender": "male",
               "percentage": "0.2"
            },
            {
               "gender": "female",
               "percentage": "0.6",
               "grade": "7-9"
            },
            {
               "grade": "10-12",
               "percentage": "0.1",
               "gender": "male"
            },
            {
               "percentage": "0.1",
               "gender": "unspecified",
               "grade": "10-12"
            },
            {
               "grade": "10-12",
               "gender": "female",
               "percentage": "0.8"
            }
         ],

         "neighborhood_name": [{
               "percentage": "0.2",
               "neighborhood": "atwood"
            },
            {
               "region": "bluff",
               "percentage": "0.8"
            }
         ]

      }
   ]
}

Вот что я ожидаю:


{
         "id": "abc",
         "students": "elementary",
         "demo_K-2_unspecified": "0.1",
         "demo_K-2_male": "0.5",
         "demo_K-2_female": "0.4",
         "demo_3-6_male": "0.3",
         "demo_3-6_unspecified": "0.6",
         "demo_3-6_female": "0.5",
            },
      {
         "id": "def",
         "students": "midhigh",
         "demo_7-9_unspecified": "0.2",
         "demo_7-9_male": "0.2",
         "demo_7-9_female": "0.6",
         "demo_10-12_male": "0.1",
         "demo_10-12_unspecified": "0.1",
         "demo_10-12_female": "0.8",

      }

Ответы [ 2 ]

1 голос
/ 10 июля 2019

С примерами данных следующий фильтр производит желаемый результат:

.data[]
| {id, students} as $ix
| .demographics
| map( {"demo_\(.grade)_\(.gender)": .percentage} )
| $ix + add

Основная идея здесь - использовать map для создания списка пар ключ-значение, чтобы составнойобъект может быть легко создан с использованием add.

в качестве однострочного

jq '.data[] | {id,students} + (.demographics | map( {"demo_\(.grade)_\(.gender)": .percentage} ) | add)' test2.json
0 голосов
/ 27 июля 2019

в качестве альтернативы , та же самая операция JSON может быть достигнута с помощью утилиты Unix Walk-Path jtc:

bash $ <test2.json jtc -x'[data][:]' -y[id] -y[students] -y'<grade>l:<R>v[-1][gender]<N>v[-1][percentage]' -TT -TT -T'{"demo_{R}_{N}":{{}}}' -jll
[
   {
      "demo_3-6_female": "0.5",
      "demo_3-6_male": "0.3",
      "demo_3-6_unspecified": "0.2",
      "demo_K-2_female": "0.4",
      "demo_K-2_male": "0.5",
      "demo_K-2_unspecified": "0.1",
      "id": "abc",
      "students": "elementary"
   },
   {
      "demo_10-12_female": "0.8",
      "demo_10-12_male": "0.1",
      "demo_10-12_unspecified": "0.1",
      "demo_7-9_female": "0.6",
      "demo_7-9_male": "0.2",
      "demo_7-9_unspecified": "0.2",
      "id": "def",
      "students": "midhigh"
   }
]
bash $ 

здесь есть 3 пути прохождения (после объединения -x с каждым -y):

  • первый путь прохождения ([data][:][id]) будет отображать id запись, второй будет studentsпоследний соберет все demographics записей
  • , есть 3 шаблона (по одному на каждую прогулку), потому что первые две прогулки не требуют никакой интерполяции, шаблоны для них являются фиктивными (-TT),Последний шаблон преобразует последний обход в требуемый вывод.

options -j собирает все обходы во внешний массив JSON;-ll гарантирует, что шаблонные объекты JSON будут удалены (то есть обработаны как помеченные значения) и сгруппированы по релевантности обхода.

PS> Раскрытие информации: я создатель jtc - оболочки cli для операций JSON

...