jsonjq

Join multiple objects with one to many relationship


Imagine the following data (array of users which can have many roles, each user object has multiple roleIDs referenced and an array of role definitions):

{
  "users": [
    {
      "id": 1
      "roles": [
        1,
        2
      ]
    },
    {
      "id": 2
      "roles": [
        1
      ]
    }    
  ],
  "roles": [
    {
      "id": 1
      "desc": "Viewer"
    },
    {
      "id": 2
      "desc": "admin"
    }
  ]
}

How would you go about joining the two arrays "users" and "roles" in jq to achieve something like this:

"user_roles": [
  {
    userId: 1,
    "roles": [
      "Viewer",
      "admin"
    ]
  },
  {
    "userId": 2,
    "roles": [
      "Viewer"
    ]
  }
]

Solution

  • This should be a simple INDEX+JOIN operation:

    INDEX(.roles[]; .id) as $roles | .users | map({
      userId: .id,
      roles : [JOIN($roles; .roles[]; tostring; last.desc)]
    })
    
    [
      {
        "userId": 1,
        "roles": [
          "Viewer",
          "admin"
        ]
      },
      {
        "userId": 2,
        "roles": [
          "Viewer"
        ]
      }
    ]
    

    Demo

    Wrap this in {user_roles: …} if you also want to return a surrounding object.