Сжатие документа JSON с использованием jq
Я рассматриваю следующий массив объектов JSON:
[
{
"index": "index1",
"type": "type1",
"id": "id1",
"fields": {
"deviceOs": [
"Android"
],
"deviceID": [
"deviceID1"
],
"type": [
"type"
],
"country": [
"DE"
]
}
},
{
"index": "index2",
"type": "type2",
"id": "id2",
"fields": {
"deviceOs": [
"Android"
],
"deviceID": [
"deviceID2"
],
"type": [
"type"
],
"country": [
"US"
]
}
}
]
и я хотел бы сгладить его, чтобы получить:
[
{
"index": "index1",
"type": "type",
"id": "id1",
"deviceOs": "Android",
"deviceID": "deviceID1",
"country": "DE"
},
{
"index": "index2",
"type": "type",
"id": "id2",
"deviceOs": "Android",
"deviceID": "deviceID2",
"country": "US"
}
]
Я пытаюсь работать с jq
, но я не сглаживаю "fields"
. Как я должен это делать? На данный момент меня интересуют инструменты командной строки, но я также открыт для других предложений.
Ответы
Ответ 1
Это было сложно сделать.
map
(
with_entries(select(.key != "fields"))
+
(.fields | with_entries(.value = .value[0]))
)
Позвольте сломать его и объяснить его бит
-
Для каждого элемента массива...
map(...)
-
Создайте новый объект, содержащий значения для всех, кроме свойства fields
.
with_entries(select(.key != "fields"))
-
Объедините это с...
+
-
Каждый из fields
проецирует каждое из значений на первый элемент каждого массива
(.fields | with_entries(.value = .value[0]))
Ответ 2
Вы можете использовать этот фильтр:
[.[] | {index: .index, type: .type, id: .id, deviceOs: .fields.deviceOs[],deviceID: .fields.deviceID[],country: .fields.country[]}]
Вы можете проверить здесь https://jqplay.org
Ответ 3
Вот несколько вариантов, которые начинаются с объединения полей в содержащий объект с + и затем сглаживания элементов массива. Сначала мы заботимся о .fields с
.[]
| . + .fields
| del(.fields)
который оставляет нас с объектами, которые выглядят как
{
"index": "index1",
"type": [
"type"
],
"id": "id1",
"deviceOs": [
"Android"
],
"deviceID": [
"deviceID1"
],
"country": [
"DE"
]
}
тогда мы можем сгладить ключи несколькими способами.
Один из способов - использовать with_entries
| with_entries( .value = if .value|type == "array" then .value[0] else .value end )
другой способ - использовать уменьшить и setpath
| . as $v
| reduce keys[] as $k (
{};
setpath([$k]; if $v[$k]|type != "array" then $v[$k] else $v[$k][0] end)
)