Mike
Mike

Reputation: 5499

Flatten a hierarchical JSON array using JQ

Can anyone help me get the correct jq command to flatten the below example? I've seen a few other posts and I'm hacking away at it but can't seem to get it. I'd greatly appreciate any help.

Input:

[
    {
        "name": "level1",
        "children": [
            {
                "name": "level2",
                "children": [
                    {
                        "name": "level3-1",
                        "children": []
                    },
                    {
                        "name": "level3-2",
                        "children": []
                    }
                ]
            }
        ]
    }
]

Output:

[
    {
        "displayName": "level1",
        "parent": ""
    },
    {
        "displayName": "level2",
        "parent": "level1"
    },
    {
        "displayName": "level3-1",
        "parent": "level2"
    },
    {
        "displayName": "level3-2",
        "parent": "level2"
    }
]

Upvotes: 1

Views: 537

Answers (2)

peak
peak

Reputation: 116670

Here's a straightforward solution that does not involve a helper function and actually solves a more general problem. It is based on the idea of beginning by adding a "parent" key to each child, and then using .. to collect all the name/parent pairs.

So first consider:

[ walk(if type=="object" and has("children")
       then .name as $n | .children |= map(.parent = $n)
       else . end)
  | ..
  | select(type=="object" and has("name"))
  | {displayName: .name, parent}
]

This meets the requirements except that for the top-level (parentless) object, it produces a .parent value of null. That would generally be more JSON-esque than "", but if the empty string is really required, one has simply to replace the last non-trivial line above by:

| {displayName: .name, parent: (.parent // "")}

Upvotes: 2

oguz ismail
oguz ismail

Reputation: 50750

With a simple recursive function:

def f: .name as $parent | .children[] | {$parent, displayName: .name}, f;
[ {name: "", children: .} | f ]

Online demo

Upvotes: 1

Related Questions