Nest and merge JSON based on namespaces

Viewed 79

I've got the following JSON document:
(sorted by namespace; any namespace can appear multiple times)

[ {"namespace": "/"       , "exports": {"a": 10, "b": 11}}
, {"namespace": "/"       , "exports": {"c": 12, "d": 13}}
, {"namespace": "/bar"    , "exports": {"e": 14, "f": 15}}
, {"namespace": "/bar/baz", "exports": {"g": 16, "h": 17}}
]

that I need to convert into this JSON document:
(the risk of key collisions can be ignored)

{ "a": 10
, "b": 11
, "c": 12
, "d": 13
, "bar": { "e": 14
         , "f": 15
         , "baz": { "g": 16
                  , "h": 17}}}

Note that whilst nesting namespaces we only keep their basename e.g.,

/
/bar
/bar/baz
/bar/baz/bat

becomes:

{"bar": {"baz": {"bat": {}}}}

Members must be nested under their corresponding namespace object with the only expection of members of the root "/" namespace which become top-level properties.

I've scratched my head a few times over this problem as I'd like to get this done in one pass (ideally) but I'm open to any other suggestions.

1 Answers

Convert namespaces to paths and you can build the desired output using getpath/setpath built-ins.

reduce .[] as {$namespace, $exports} ({};
  ($namespace | ltrimstr("/") | split("/")) as $path
  | setpath($path; getpath($path) + $exports)
)

Online demo

Related