Преобразуйте древовидный json так, чтобы один «элемент» в списке перемещался вверх (из листа), пустые элементы удалялись - с помощью 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": "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, пока

  • Вы не можете ссылаться на такие поля, как beep1, beep2, Keep1,... в выражении jq, в любом объекте может быть любое количество дополнительных полей.
  • Вам следует обращаться только к полям: товар, название, описание.
  • сохраняйте порядок полей прежним
  • если вы добавляете конечный элемент в родительский массив «элемент», попробуйте добавить его в то же место, где находился каталог (в примере, «whatever3» в местоположение удаленного операнда2)
  • Вы не перемещаете листы, если в одном и том же массиве элементов имеется более одного элемента (вы перемещаете лист вверх только в том случае, если это один элемент в папке).

Таким образом, вывод должен быть таким:

{
    "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": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

Повтор «сохранять порядок полей неизменным»: поля в объектах не имеют порядка, он есть только у элементов в массивах.

pmf 22.08.2024 14:31

Похоже, jq сохраняет их и не перетасовывает, если только вы не попытаетесь что-то там сделать, когда применяете фильтры.

Tamás Horváth 22.08.2024 14:41
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
2
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сжимайте снизу вверх, сначала рекурсивно спускаясь в каждый массив .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 (Демо).

Большое спасибо, это также полностью соответствует ожиданиям

Tamás Horváth 23.08.2024 07:57

Другие вопросы по теме