Я хочу преобразовать приведенный ниже ввод в вывод JSON родитель-потомок, используя преобразование dataweave. Пожалуйста, дайте мне знать, если кто-нибудь работал над этим раньше. Я добавил пример ввода и вывода json ниже.
Обновленный пост с дополнительными узлами: мне нужно несколько родительских узлов с уровнем местоположения = 1 с соответствующими иерархиями.
Введите JSON-формат:
[
{
"ENTITY_ID": 1,
"PARENT_EID": 1,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "123"
},
{
"ENTITY_ID": 2,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "234"
},
{
"ENTITY_ID": 3,
"PARENT_EID": 2,
"LOCATION_LEVEL": 3,
"LOCATION_CODE": "345"
},
{
"ENTITY_ID": 4,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "567"
},
{
"ENTITY_ID": 5,
"PARENT_EID": 5,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "012"
},
{
"ENTITY_ID": 6,
"PARENT_EID": 5,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "023"
}
]
Формат вывода json:
[
{
"ENTITY_ID": 1,
"PARENT_EID": 1,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "123",
"CHILDRENS":[
{
"ENTITY_ID": 2,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "234"
"CHILDRENS":[{
"ENTITY_ID": 3,
"PARENT_EID": 2,
"LOCATION_LEVEL": 3,
"LOCATION_CODE": "345"
}]
},
{
"ENTITY_ID": 4,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "567"
}
]
},
{
"ENTITY_ID": 5,
"PARENT_EID": 5,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "012",
"CHILDRENS":[{
"ENTITY_ID": 6,
"PARENT_EID": 5,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "023"
}]
}
]
Попробуйте это:
%dw 2.0
output application/json
var data = [
{
"ENTITY_ID": 1,
"PARENT_EID": 1,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "123"
},
{
"ENTITY_ID": 2,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "234"
},
{
"ENTITY_ID": 3,
"PARENT_EID": 2,
"LOCATION_LEVEL": 3,
"LOCATION_CODE": "345"
},
{
"ENTITY_ID": 4,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "567"
},
{
"ENTITY_ID": 5,
"PARENT_EID": 5,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "012"
},
{
"ENTITY_ID": 6,
"PARENT_EID": 5,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "023"
}
]
var top = data filter ($.LOCATION_LEVEL == 1)
fun insert(t,e) = t match {
case {} -> e
case tree if (tree.ENTITY_ID == e.PARENT_EID) -> do {
var node = tree - "CHILDREN"
var children = if (tree.CHILDREN?) (tree.CHILDREN + e) else [e]
---
{(node),CHILDREN: children}
}
case tree if (tree.ENTITY_ID != e.PARENT_EID) -> do {
var node = tree - "CHILDREN"
var children = tree.CHILDREN map ($ insert e)
---
{(node), (CHILDREN: children) if (not isEmpty(children))}
}
else -> $
}
---
top map (topnode) -> (
(data -- top) orderBy $.ENTITY_ID reduce ((e, acc=topnode) -> acc insert e)
)
Протестируйте его с большим количеством входных данных, и вам может потребоваться скорректировать код, если некоторые другие тестовые примеры не пройдут.
Вы (или, может быть, кто-то другой) можете переписать это, используя оператор update
, по сравнению с созданием переменных node
и children
, как это делаю я.
Изолируйте запись, которая вызывает проблему, затем проверьте ее и воспроизведите поведение в своих образцах данных. Также будет полезно, если вы предоставите сообщение об ошибке, которое вы получите.
В случае повторного запуска с location_level 1 означает новую иерархию, такой тип senario не работает, как новый уровень Location 1.
Что делать, если у меня есть другой узел с местоположением 1, как показано ниже { "ENTITY_ID": 2, "PARENT_EID": 2, "LOCATION_LEVEL": 1, "LOCATION_CODE": "156" }
Итак, мы не будем ходить туда-сюда, вам нужно предоставить образцы данных, которые фиксируют все перестановки. Затем вам нужно изменить свой исходный пост, чтобы он содержал образцы данных. Кроме того, вы ДОЛЖНЫ предоставить алгоритмические детали (т. е. логику) того, как вы связываете родительские и дочерние узлы. Тогда и только тогда я смогу помочь дальше.
Только что обновил мой вопрос дополнительными узлами. Спасибо за ваш ответ
Обратите внимание, используя ваше выражение dataweave, я не получаю массив иерархических данных, как в скобках [ ]. Это в скобках {}. Еще раз спасибо :)
Также обратите внимание, что это пример данных. В реальных данных есть около 5000 списков узлов, которые я преобразовываю. Я получаю сообщение об ошибке Java.lang.stackoverflow. Есть ли способ оптимизировать это?
Что касается логики, то она основана исключительно на отношении родительского идентификатора eid и идентификатора сущности, а также на уровне местоположения. Если уровень местоположения = 1, то его родительский узел
Ты здесь, Джордж?
Да, я Сандеш, но я занят на этой неделе — возможно, я посмотрю на него в выходные.
Пожалуйста, перепроверьте свои образцы данных - кажется, что последняя запись должна иметь LOCATION_LEVEL: 2
Внесены обновления в решение, чтобы отразить ваши последние образцы данных. Если код по-прежнему не работает с вашими реальными данными, то, скорее всего, вам не хватает дальнейших перестановок ваших данных, что, я считаю, дало вам неплохой старт;)
%dw 2.0
output application/json
var Input = [
{
"ENTITY_ID": 1,
"PARENT_EID": 1,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "123"
},
{
"ENTITY_ID": 2,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "234"
},
{
"ENTITY_ID": 3,
"PARENT_EID": 2,
"LOCATION_LEVEL": 3,
"LOCATION_CODE": "345"
},
{
"ENTITY_ID": 4,
"PARENT_EID": 1,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "567"
},
{
"ENTITY_ID": 5,
"PARENT_EID": 5,
"LOCATION_LEVEL": 1,
"LOCATION_CODE": "012"
},
{
"ENTITY_ID": 6,
"PARENT_EID": 5,
"LOCATION_LEVEL": 2,
"LOCATION_CODE": "023"
}
]
fun hasChildren(id) = sizeOf(Input filter (($.PARENT_EID == id) and ($.ENTITY_ID != $.PARENT_EID)))
fun createTree(data) = if (hasChildren(data.ENTITY_ID) > 0)data ++ {"CHILDRENS": (Input filter (($.PARENT_EID == data.ENTITY_ID) and ($.ENTITY_ID != $.PARENT_EID))) map ((item, index) -> createTree(item)) } else data
---
Input filter ($.ENTITY_ID == $.PARENT_EID) map ((item, index) -> createTree(item))
Работает до 8 уровня дочерних узлов. однако, когда я пытаюсь вставить дочерний узел для 4-го родителя, это не удается. Спасибо за ответ, это много значит