Если немного абстрагироваться, довольно просто написать универсальную функцию отображения дерева. Затем мы можем предоставить две функции обратного вызова: одну для поиска дочерних узлов ввода и одну для построения выходного узла на основе ввода и сопоставленных дочерних элементов. Такая функция оказывается удивительно простой:
const mapTree = (getChildren, transformNode) => (tree) =>
transformNode (
tree,
(getChildren (tree) || []) .map (mapTree (getChildren, transformNode))
)
Для ваших данных getChildren
- это просто (node) => node._children
И преобразование узла может быть таким простым:
const transformNode = (node, children) =>
({
id: node.$id, // or a randomizing call?
text: node.name,
icon: "fas fa-plus", // is this really a fixed value?
subNode: children
})
Сложив это вместе, мы получим
const mapTree = (getChildren, transformNode) => (tree) =>
transformNode (
tree,
(getChildren (tree) || []) .map (mapTree (getChildren, transformNode))
)
const kids = (node) => node._children
const transformNode = (node, children) =>
({
id: node.$id,
text: node.name,
icon: "fas fa-plus",
subNode: children
})
const myTransform = mapTree (kids, transformNode)
const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }
console .log (myTransform (jsonData))
Это немного отличается от запрошенного вами результата. Вы написали subNode: { ... }
, но вместо этого я возвращаю массив объектов, subNodes: [ ... ]
, так как я не вижу здесь никакого реального смысла простого объекта.
Кроме того, это приведет к пустомуsubNodes
массив, если входной узел не имеет дочерних элементов. Если вы предпочитаете не иметь свойства subNodes
, вы можете заменить
subNode: children
чем-то вроде
...(children .length ? {subNode: children} : {})
Очевидно, вам не нужны именованные помощники, и вы могли бы вызвать mapTree
с анонимными функциями, такими как:
const myTransform = mapTree (
(node) => node._children,
(node, children) =>
({
id: node.$id,
text: node.name,
icon: "fas fa-plus",
subNode: children
})
)
Эту функцию mapTree
было очень легко написать, так как мне не нужно было думать ни о каких деталях формата вывода или ввода, как я ее написал. Но, возможно, эта абстракция мне не поможет, и я никогда не буду ее использовать, кроме как здесь. Если это так, я могу просто переработать абстрактную версию, подключив жестко закодированные обратные вызовы напрямую. Только с небольшой манипуляцией, это превратит его в эту версию:
const newTransform = (node) =>
({
id: node.$id,
text: node.name,
icon: "fas fa-plus",
subNode: (node._children || []).map(newTransform)
})
const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }
console .log (newTransform (jsonData))
Здесь есть важный момент. Эту универсальную функцию было написать гораздо проще, чем если бы я попытался написать что-то для непосредственного преобразования вашего формата. Хотя в слишком ранней абстракции есть опасность, она также может предложить значительные преимущества. Я мог бы предпочесть оставить только эту последнюю версию, но общая абстракция упростила ее разработку.