Relequestual
Relequestual

Reputation: 12295

How do I modify a child object if it exists in array of objects using jq?

I'm trying to use jq to modify json data at various levels of an API request or response to enable support for API versioning.

Here's my (simplified) test JSON:

[
  {
    "note": null,
    "patient_id": 1,
    "phenotypes": [
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 1,
        "person_id": 1
      },
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 1,
        "person_id": 1
      }
    ]
  },
  {
    "note": null,
    "patient_id": 2
  },
  {
    "note": null,
    "patient_id": 3,
    "phenotypes": [
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 3,
        "person_id": 3
      },
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 3,
        "person_id": 3
      }
    ]
  }
]

I have an array of objects. Each object MAY have "phenotypes", which I need to modify the content of, as well as removing "note" from the top level object.

Currently my jq is as follows:

[ map(del(.note, .age)) | .[] | select(.phenotypes != null) | .phenotypes |= map(del(.person_id)) ]

This almost works, but because of select(.phenotypes != null), the second object in the array never makes it back after filtering.

I have also tried using if-then-else (end), however I couldn't make it not error, and I can't find any examples or documentation that suggests it can be used for further expression.

My expected output is the following:

[
  {
    "patient_id": 1,
    "phenotypes": [
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 1
      },
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 1
      }
    ]
  },
  {
    "patient_id": 2
  },
  {
    "patient_id": 3,
    "phenotypes": [
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 3
      },
      {
        "name": "Breast carcinoma",
        "observation": "present",
        "patient_id": 3
      }
    ]
  }
]

note has been removed from root. person_id has been removed from phenotypes.

Upvotes: 2

Views: 206

Answers (1)

Remy Sharp
Remy Sharp

Reputation: 4560

This works for me:

map(del(.note, .age)) |
map( 
    if .phenotypes then 
        (.phenotypes |= map(del(.person_id)))
    else
        .
    end 
)

Working example

Upvotes: 3

Related Questions