Delphi SuperObject - is there a (recursive) search function that tells where a value can be found?

675 views Asked by At

I'm using SuperObject to create and manipulate a simple hierarchical structure in JSON.

My goal is to transform a set of objects {"id":..., "name":..., "parent":...} into a hierarchical structure. Example:

I want to transform this

    {"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"},

into this

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

(This structure can vary, i.e. there is no fixed model. Which probably means the solution must be recursive).

I think the way to achieve this is:

  • for each object to add,
    • if there is no parent, add it to the output json, at the top;
    • if there is a parent, find where the parent is in the output json.
    • add the object to the output json under the parent.

To do this, I was looking for a way to retrieve the path of an object, like

function findpathinObject(key:string, value:string, object:iSuperObject):string

which would return the "path" of the value found.

In my example, findpathinObject("parent", "0003.1", newObject) would return 'items[2].items[0]'

Is this a good approach? Is there something that resolves my issue without making a new function?

the closest I've seen is this SuperObject - Extract All but I don't know if that can be changed to return the path it is looking in, or the path where it finally found the value...

Thanks

2

There are 2 answers

0
costateixeira On BEST ANSWER

Got this from Python: Sorting JSON object(s) into a Hierarchy

In Delphi (it works, here is an extract for guidance):

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;
1
Arnaud Bouchez On

SuperObject is a JSON access library, not a data processing library. So there is nothing like this available in the box.

You just need to implement the extraction logic in pascal code, using SuperObject for reading the input, and creating the nested output.