У меня есть json, похожий на дерево файлов или папок:
{
"item": [
{
"name": "objects",
"description": "root f",
"item": [
{
"name": "external",
"item": [
{
"name": "buuu",
"keep1": {}
},
{
"name": "biii",
"keep1": {}
}
],
"description": "Whatever comment."
},
{
"name": "afolder",
"item": [
{
"name": "methods",
"item": [
{
"name": "blaaa",
"keep1": {}
},
{
"name": "empty",
"description": "Whatever2.",
"item": []
},
{
"name": "partner1",
"item": [
{
"name": "operand",
"item": [
{
"name": "whetever4",
"beep1": { },
"beep2": []
}
]
}
]
},
{
"name": "empty2",
"description": "Whatever3."
},
{
"name": "partner2",
"item": [
{
"name": "operandx",
"beep2": []
},
{
"name": "operand2",
"item": [
{
"name": "whatever3",
"beep1": { },
"beep2": []
}
]
}
]
}
]
}
]
}
]
}
]
}
Дерево состоит из .item[]
(необязательно) массивов и .name
(необязательно .description
) полей. Если полей больше, то элемент нельзя удалить!
Итак, есть такие предметы, как
objects/ --> with "root f" comment
external --> is an item that could be deleted because has no extra fields
external/buu and external/bii --> Are non-deletable items, do not move them up to "objects" folder! As there are two items under "exernal"! You only move up single items in a folder!
objects/afolder
objects/afolder/methods
empty and empty2 are to be deleted items (leaf, and only name, description or item fields are there, and the items is practically empty.
objects/afolder/methods/partner1
operand --> is a folder to delete as you will move the "operand/whetever4" under objects/afolder/methods/partner1, and this "operand" will be empty!
objects/afolder/methods/partner2
operand2 --> must be deleted after the single leaf "whatever3" is moved under objects/afolder/methods/partner2 - next to "operandx" ideally
Поэтому фильтр jq
должен создавать реорганизованный json, пока
Таким образом, вывод должен быть таким:
{
"item": [
{
"name": "objects",
"description": "root f",
"item": [
{
"name": "external",
"item": [
{
"name": "buuu",
"keep1": {}
},
{
"name": "biii",
"keep1": {}
}
],
"description": "Whatever comment."
},
{
"name": "afolder",
"item": [
{
"name": "methods",
"item": [
{
"name": "blaaa",
"keep1": {}
},
{
"name": "partner1",
"item": [
{
"name": "whetever4",
"beep1": { },
"beep2": []
}
]
},
{
"name": "partner2",
"item": [
{
"name": "operandx",
"beep2": []
},
{
"name": "whatever3",
"beep1": { },
"beep2": []
}
]
}
]
}
]
}
]
}
]
}
Сжимайте снизу вверх, сначала рекурсивно спускаясь в каждый массив .item
, затем выполняя удаления и переход из подчиненного массива .item
в текущий элемент.
def candidate(m): objects
| select((.item | length) == m and del(.item,.name,.description) == {});
def condense: (objects.item | arrays[]) |= condense
| (.item | arrays) |= . - map(candidate(0)) | candidate(1) = .item[0];
condense
{
"name": "objects",
"description": "root f",
"item": [
{
"name": "external",
"item": [
{
"name": "buuu",
"keep1": {}
},
{
"name": "biii",
"keep1": {}
}
],
"description": "Whatever comment."
},
{
"name": "methods",
"item": [
{
"name": "blaaa",
"keep1": {}
},
{
"name": "whetever4",
"beep1": {},
"beep2": []
},
{
"name": "partner2",
"item": [
{
"name": "operandx",
"beep2": []
},
{
"name": "whatever3",
"beep1": {},
"beep2": []
}
]
}
]
}
]
}
Примечание. В отличие от ожидаемого результата, это также уплотняет пути /
(корневой), /objects/afolder
и /objects/afolder/methods/partner1
, поскольку все они имеют (согласно вашим правилам) только один элемент и никаких других ключей. Чтобы этого не произошло с корнем как особым случаем, начните с обработки элементов корня напрямую, т. е. .item[] |= condense
(Демо).