Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq denormalize a nested field

Tags:

json

jq

disclaimer: indeed, there are already different answers (like JQ Join JSON files by key or denormalizing JSON with jq) for but none of them helped me yet or did have different circumstances I was unable to derive a solution from ;/


I have 2 files, both are lists of objects where one of them ha field references to object ids of the other one

given

[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1"
    }
  }
]

and

[
  {
    "id": "5de82d5072f4a72ad5d5dcc1",
    "name": "FooBar"
  }
]

my goal would be to get a denormalized object list:

expected

[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1",
      "name": "FooBar"
    }
  }
]

while I'm able to do the main parts, I didn't challenged to bring both together yet:

with example 1

jq -s '(.[1][] | select(.id == "5de82d5072f4a72ad5d5dcc1"))' objects.json referredObjects.json

I get

{
  "id": "5de82d5072f4a72ad5d5dcc1",
  "name": "FooBar"
}

and with example 2

jq -s '.[0][] | .reference = {}' objects.json referredObjects.json

I can manipulate any .reference getting

{
  "id": "5b9f50ccdcdf200283f29052",
  "reference": {}
}

(even I loose the list structure)

But: I can't do s.th. like

execpted "join"

jq -s '.[0][] as $obj | $obj.reference = (.[1][] | select(.id == $obj.reference.id))' objects.json referredObjects.json

even approaches with foreach or reduce looks promising

jq -s '[foreach .[0][] as $obj ({}; .reference.id = ""; . + $obj )]' objects.json referredObjects.json

=>

[
  {
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1"
    },
    "id": "5b9f50ccdcdf200283f29052"
  }
]

where I expected to get the same as in second example

I end up in headaches and looking forward to write a ineffective while routine in any language ... hopefully I would appreciate any help on this

~Marcel

like image 253
childno͡.de Avatar asked Jul 05 '26 07:07

childno͡.de


1 Answers

Transform the second file into an object where ids and names are paired and use it as a reference while updating the first file.

$ jq '(map({(.id): .}) | add) as $idx
      | input
      | map_values(.reference = $idx[.reference.id])' file2 file1
[
  {
    "id": "5b9f50ccdcdf200283f29052",
    "reference": {
      "id": "5de82d5072f4a72ad5d5dcc1",
      "name": "FooBar"
    }
  }
]
like image 53
oguz ismail Avatar answered Jul 08 '26 02:07

oguz ismail