Delphi SuperObject - есть ли (рекурсивная) функция поиска, которая сообщает, где можно найти значение?
Я использую SuperObject для создания и управления простой иерархической структурой в JSON.
Моя цель - преобразовать набор объектов {"id":..., "name":..., "parent":...} в иерархическую структуру. Пример:
Я хочу изменить это
{"id": "0001","name": "item0001", "parent":""},
{"id": "0002","name": "item0002", "parent":""},
{"id": "0003","name": "item0003", "parent":""},
{"id": "0003.1","name": "item0003.1", "parent":"0003"},
{"id": "0003.1.1","name": "item0003.1.1", "parent":"0003.1"},
в это
{
"items": [
{
"id": "0001",
"name": "item0001"
},
{
"id": "0002",
"name": "item0002"
},
{
"id": "0003",
"name": "item0003",
"items": [
{
"id": "0003.1",
"name": "item0003.1",
"items": [
{
"id": "0003.1.1",
"name": "item0003.1.1"
}
]
}
]
}
]
}
(Эта структура может варьироваться, т. Е. Нет фиксированной модели. Это, вероятно, означает, что решение должно быть рекурсивным).
Я думаю, что способ достичь этого:
- для каждого объекта, чтобы добавить,
- если нет родителя, добавьте его в вывод json, вверху;
- если есть родитель, найдите, где родитель находится в выводе json.
- добавить объект в выходной JSON под родителем.
Для этого я искал способ получить путь к объекту, например
function findpathinObject(key:string, value:string, object:iSuperObject):string
который вернул бы "путь" найденного значения.
В моем примере findpathinObject("parent", "0003.1", newObject) вернул бы 'items[2].items[0]'
Это хороший подход? Есть ли что-то, что решает мою проблему без создания новой функции?
самый близкий, который я видел, - это SuperObject - Extract All, но я не знаю, можно ли это изменить, чтобы он возвращал путь, по которому он ищет, или путь, по которому он наконец нашел значение...
Спасибо
1 ответ
Получил это из Python: сортировка объектов JSON в иерархию
В Delphi (это работает, вот выдержка для руководства):
function ProcessObject(const aAsObject: iSuperObject): iSuperObject;
var
var KeyedObject: iSuperObject
item: iSuperObject;
ArrayItem: iSuperObject;
parent, tgt: iSuperObject;
begin
KeyedObject := SO('{}');
for ArrayItem in aAsObject do
begin
KeyedObject[ArrayItem['id'].AsString] := ArrayItem;
end;
// iterate through each item in the `myJson` list.
for item in aAsObject do
begin
// does the item have a parent?
if assigned(item['parent.id']) then
begin
// get the parent item
if (assigned(item['parent']) and assigned(item['parent.id'])) then
begin
if (assigned(KeyedObject[item['parent'].AsString])) then
parent := KeyedObject[item['parent.id'].AsString];
// if the parent item doesn't have a "children" member,
// we must create one.
if not(assigned(parent['children'])) then
parent['children'] := SO('{[]}');
// add the item to its parent's "children" list.
parent['children[]'] := item;
end;
end;
end;
tgt := SO('{}');
for item in aAsObject do
if not assigned(item['parent']) then
tgt[] := item;
result := tgt;
end;
SuperObject - это библиотека доступа JSON, а не библиотека обработки данных. Так что в коробке нет ничего подобного.
Вам просто нужно реализовать логику извлечения в коде Паскаль, используя SuperObject для чтения ввода и создания вложенного вывода.