costateixeira
costateixeira

Reputation: 131

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

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:

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

Upvotes: 2

Views: 733

Answers (2)

costateixeira
costateixeira

Reputation: 131

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;

Upvotes: 1

Arnaud Bouchez
Arnaud Bouchez

Reputation: 43023

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.

Upvotes: 0

Related Questions