skip to Main Content

Sorry for a noob question. I got two json that I need to merge. And I’m not really sure what operation/function to use in jq, so please enlighten me. Thanks!

color.json

[{"id":1,"color":"red"},{"id":2,"color":"green"},{"id":3,"color":"blue"}]

shape.json

[
  {
    "shape": "square",
    "color": {
      "id": 1,
      "name": "red"
    },
    "texture": "smooth"
  },
  {
    "shape": "circle",
    "color": {
      "id": 2,
      "name": "green"
    },
    "texture": "smooth"
  },
  {
    "shape": "triangle",
    "color": {
      "id": 3,
      "name": "blue"
    },
    "texture": "smooth"
  },
  {
    "shape": "triangle",
    "color": {
      "id": 3,
      "name": "blue"
    },
    "texture": "rough"
  }
]

Desired output

[
  {
    "id": 1,
    "color": "red",
    "shapes": [
      {
        "shape": "square",
        "texture": "smooth"
      }
    ]
  },
  {
    "id": 2,
    "color": "green",
    "shapes": [
      {
        "shape": "circle",
        "texture": "smooth"
      }
    ]
  },
  {
    "id": 3,
    "color": "blue",
    "shapes": [
      {
        "shape": "triangle",
        "texture": "smooth"
      },
      {
        "shape": "triangle",
        "texture": "rough"
      }
    ]
  }
]

I tried using jq 'JOIN(INDEX(inputs[];.id);.[];.color.id | tostring;add)' shape.json color.json. But it’s not exactly what I’m aiming for.

2

Answers


  1. Seem like you can get the desired output by just using the shape.json.

    You could this (probably not optimised) filter to get to the desired output:

    group_by(.shape) 
        | map({ 
            id: .[0].color.id, 
            color: .[0].color.name, 
            shapes: map({ shape, texture }) 
        })
    

    GIves:

    [
      {
        "id": 2,
        "color": "green",
        "shapes": [
          {
            "shape": "circle",
            "texture": "smooth"
          }
        ]
      },
      {
        "id": 1,
        "color": "red",
        "shapes": [
          {
            "shape": "square",
            "texture": "smooth"
          }
        ]
      },
      {
        "id": 3,
        "color": "blue",
        "shapes": [
          {
            "shape": "triangle",
            "texture": "smooth"
          },
          {
            "shape": "triangle",
            "texture": "rough"
          }
        ]
      }
    ]
    

    Online demo

    Login or Signup to reply.
  2. Here’s a reduce-based approach which simply iterates over the shape.json items, adding them to the INDEXed object from colors.json. A final map(.) re-converts the object into an array:

    jq '
      reduce input[] as $i (INDEX(.id);
        .[$i.color.id | tostring].shapes += [$i | {shape, texture}]
      ) | map(.)
    ' color.json shape.json
    
    [
      {
        "id": 1,
        "color": "red",
        "shapes": [
          {
            "shape": "square",
            "texture": "smooth"
          }
        ]
      },
      {
        "id": 2,
        "color": "green",
        "shapes": [
          {
            "shape": "circle",
            "texture": "smooth"
          }
        ]
      },
      {
        "id": 3,
        "color": "blue",
        "shapes": [
          {
            "shape": "triangle",
            "texture": "smooth"
          },
          {
            "shape": "triangle",
            "texture": "rough"
          }
        ]
      }
    ]
    

    Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search