flatten nested structure by two keys

32 Views Asked by At

I have a json that represents a mental map. Observe that there are 4 types of things: Questions, Ideas, Pros, Cons. And that each sentence has a unique id.

{ "null":"top of the map",
  "Question": [
    {
      "root": "What should we do about the one ring?",
      "Idea": [
        {
          "gg": "Give it to golumm"
        },
        {
          "gh": "Give it to humans"
        },
        {
          "bm": "Burn it in mordor",
          "pro": [
            {
              "ow": "its the only way to destroy it"
            },
            {
              "ofora": "once and for all"
            }
          ],
          "con": [
            {
              "dr": "the road is extremely dangerous"
            }
          ]
        }
      ]
    },
    {
      "root2": "Why do we need to destroy it?"
    }
  ]
}

And I need to transform it into a flat array like this:

[
  {
    "kind": "Question",
    "parent": "null",
    "id": "root",
    "label": "What should we do about the one ring?"
  },
  {
    "kind": "Idea",
    "parent": "root",
    "id": "gg",
    "label": "Give it to golumm"
  },
  {
    "kind": "Idea",
    "parent": "root",
    "id": "gh",
    "label": "Give it to humans"
  },
  {
    "kind": "Idea",
    "parent": "root",
    "id": "bm",
    "label": "Burn it in mordor"
  },
  {
    "kind": "pro",
    "parent": "bm",
    "id": "ow",
    "label": "its the only way to destroy it"
  },
  {
    "kind": "pro",
    "parent": "bm",
    "id": "ofora",
    "label": "once and for all"
  },
  {
    "kind": "pro",
    "parent": "bm",
    "id": "dr",
    "label": "the road is extremely dangerous"
  },
  {
    "kind": "Question",
    "parent": "null",
    "id": "root2",
    "label": "Why do we need to destroy it?"
  }
]

Now this is my current jsonata query:

(
    $eachNode:=function($parent,$current){
        $current.{
            "kind":  $parent.$keys()[1],
            "parent":$parent.$keys()[0],
            "id":    $keys()[0],
            "label": $lookup($,$keys()[0])}
        };

$recursive:=function($parent,$tree){
    ($tree.$eachNode($parent,$tree))~>
    $append($tree.$recursive($,$.*))~>
    $distinct()
    
};

$.Question.$recursive(%,$)[$exists(label)]
)

And it happens to work!!

Here is on the playground:

https://try.jsonata.org/1zsmV1Qmx

But I don't understand why it works?

for example the [$exists(label)] filter at the end is hack, because witouth several objects in different states of completion are added to the result array.

The query just happens to work. And there are probably much better ways to do it.

Can you help me develop a more canonical and readable jsonato query to achieve the same result?

0

There are 0 best solutions below