JSON transformation with JQ / pyjq. Move objects from an object array to another array, matched by a identity field

Viewed 97

I would like to add the orders[].packages[].status field to the orders[].contents[] with the matching packagenumber.

Input JSON:

{
  "orders": [
    {
      "code": 2389,
      "packages": [
        {
          "packagenumber": 3929,
          "status": 100
        },
        {
          "packagenumber": 3930,
          "status": 110
        }
      ],
      "contents": [
        {
          "contentid": 398,
          "description": "closet",
          "packagenumber": 3929
        },
        {
          "contentid": 399,
          "description": "rice",
          "packagenumber": 3929
        },
        {
          "contentid": 400,
          "description": "foo",
          "packagenumber": 3930
        }
      ]
    },
    {
      "code": 2390,
      "packages": [
        {
          "packagenumber": 3930,
          "status": 110
        },
        {
          "packagenumber": 3931,
          "status": 150
        }
      ],
      "contents": [
        {
          "contentid": 500,
          "description": "bar",
          "packagenumber": 3931
        },
        {
          "contentid": 501,
          "description": "snicker",
          "packagenumber": 3931
        },
        {
          "contentid": 502,
          "description": "mars",
          "packagenumber": 3930
        }
      ]
    }
  ]
}

Desired output JSON:

{
  "orders": [
    {
      "code": 2389,
      "contents": [
        {
          "contentid": 398,
          "description": "closet",
          "packagenumber": 3929,
          "status": 100
        },
        {
          "contentid": 399,
          "description": "rice",
          "packagenumber": 3929,
          "status": 100
        },
        {
          "contentid": 400,
          "description": "foo",
          "packagenumber": 3930,
          "status": 110
        }
      ]
    },
    {
      "code": 2390,
      "contents": [
        {
          "contentid": 500,
          "description": "bar",
          "packagenumber": 3931,
          "status": 150
        },
        {
          "contentid": 501,
          "description": "snicker",
          "packagenumber": 3931,
          "status": 150
        },
        {
          "contentid": 502,
          "description": "mars",
          "packagenumber": 3930,
          "status": 110
        }
      ]
    }
  ]
}

This moves the packages to the contents:

{shipments: [.orders[] | .packages as $packages | {code:  .code, contents: [(.contents[] | ., $packages )] } ]}

With select, it is possible to get the a package, but I don't get the package that matches the packagenumber of the content work.

packages: .packages[] | select(.packagenumber==3930)

Question:

  • How can the input transformed to the desired output format? Using pyjq or jqplay.org?
1 Answers

You're looking for something like this:

.orders[] |= (
  ( .packages | INDEX(.packagenumber) ) as $r
  | .contents[] |= . + ($r[.packagenumber | tostring] | {status})
  | del(.packages)
)

Online demo

Related