jq — найдите имя массива внутри объекта JSON и затем получите содержимое массива

#arrays #json #sorting #select #jq

#массивы #json #сортировка #выберите #jq

Вопрос:

У меня есть следующий массив JSON

 [
    {
        "city": "Seattle",
        "array10": [
            "1",
            "2"
        ]
    },
    {
        "city": "Seattle",
        "array11": [
            "3"
        ]
    },
    {
        "city": "Chicago",
        "array20": [
            "1",
            "2"
        ]
    },
    {
        "city": "Denver",
        "array30": [
            "3"
        ]
    },
    {
        "city": "Reno",
        "array50": [
            "1"
        ]
    }
]
  

Моя задача заключается в следующем: для каждого "city" значения, которые известны, получить имена массивов и для каждого массива распечатать / отобразить его содержимое. Названия городов и массивов уникальны, содержимое массивов — нет.

Результат должен выглядеть следующим образом:

 Now working on Seattle
Seattle has the following arrays: 
array10
array11
Content of the array10
1
2
Content of the array11
3

Now working on Chicago
Chicago has the following arrays: 
array20
Content of the array array20
1
2

Now working on Denver
Denver has the following arrays: 
array30
Content of the array array30
3

Now working on Reno
Denver has the following arrays: 
array50
Content of the array array50
1
  

Теперь для каждого названия города (которое предоставлено / известно) Я могу найти имена массивов, используя следующий фильтр (очевидно, я могу поместить названия городов в переменные):

 jq  -r .[] | select ( .name | test("Seattle") ) | del (.name) | keys |@tsv
  

Затем присвоите эти имена переменной bash и выполните итерацию в новом цикле, чтобы получить содержимое каждого массива.

Хотя я могу получить то, что хочу, с помощью приведенного выше, мой вопрос — есть ли более эффективный способ сделать это с помощью jq?

И второй, связанный с этим вопрос — если бы мой JSON имел следующую структуру ниже, облегчило бы это мою задачу с точки зрения скорости / эффективности / простоты?

 [
    {
        "name": "Seattle",
        "content": {
            "array10": [
                "1",
                "2"
            ],
            "array11": [
                "3"
            ]
        }
    },
    {
        "name": "Chicago",
        "content": {
            "array20": [
                "1",
                "2"
            ]
        }
    },
    {
        "name": "Denver",
        "content": {
            "array30": [
                "3"
            ]
        }
    },
    {
        "name": "Reno",
        "content": {
            "array50": [
                "1"
            ]
        }
    }
]
  

Комментарии:

1. Какой формат JSON вы собираетесь выбрать для 1-й или 2-й версии? На какой версии должны основываться ответы?

2. @Inian, тот, который является наиболее эффективным / простым, но я не знаю, поэтому я спросил об обоих. У меня уже есть собственное решение для 1-й версии, но если решение для 2-й версии JSON было бы проще, тогда мне нужно сначала преобразовать 1-ю версию во 2-ю версию и применить к ней фильтр / решение.

Ответ №1:

Используя параметр командной строки -r, следующая программа выдает выходные данные, как показано ниже:

 group_by(.city)[]
| .[0].city as $city
| map(keys_unsorted[] | select(test("^array"))) as $arrays
| "Now working on ($city)",
  "($city) has the following arrays:",
  $arrays[],
  (.[] | to_entries[] | select(.key | test("^array"))
   | "Content of the (.key)", .value[])
  

Вывод

 Now working on Chicago
Chicago has the following arrays:
array20
Content of the array20
1
2
Now working on Denver
Denver has the following arrays:
array30
Content of the array30
3
Now working on Reno
Reno has the following arrays:
array50
Content of the array50
1
Now working on Seattle
Seattle has the following arrays:
array10
array11
Content of the array10
1
2
Content of the array11
3