Home > other >  JQ: Populate json data using a json template
JQ: Populate json data using a json template

Time:11-11

I'd like to transform a "raw" json data transforming to other json structure.

For example:

def template:
{
  "id": "$id",
  "practitioner": "$practitioner",
  "patient": {
    "name": "$patientName",
    "familyName": "$patientFamilyName"
  }
}
;

My data.json is:

[
  {
    "id": "id1",
    "practitioner": {
      "practitionerKey1": "practitionerValue1",
      "practitionerKey2": "practitionerValue2"
    },
    "name": "John",
    "familyName": "Smith"
  },
  {
    "id": "id2",
    "practitioner": {
      "practitionerKey1": "practitionerValue1",
      "practitionerKey2": "practitionerValue2"
    },
    "patientName": "Samuel",
    "patientFamilyName": "Schnaider"    
  }
]

My desired result would be:

[
  {
    "id": "id1",
    "practitioner": {
      "practitionerKey1": "practitionerValue1",
      "practitionerKey2": "practitionerValue2"
    },
    "patient": {
      "name": "John",
      "familyName": "Smith"
    }
  },
  {
    "id": "id2",
    "practitioner": {
      "practitionerKey1": "practitionerValue1",
      "practitionerKey2": "practitionerValue2"
    },
    "patient": {
      "name": "Samuel",
      "familyName": "Schnaider"
    }
  }
]

Any ideas about how to map above data json and populate it using a json template with JQ?

CodePudding user response:

The "query-by-example" approach you envision in the question is do-able, though it is error-prone (and indeed as @pmf pointed out, your example contains an error). This is how to realize the "QBE" approach based on matching "$-names" with key names:

def matchName($name):
   first(.. | objects | to_entries[] | select(.key == $name) | .value) // null ;

def fillin($t):
  . as $in
  | $t
  | walk(if type == "string" and startswith("$")
         then .[1:] as $s | $in | matchName($s)
         else . end);
     
map(fillin(template))

CodePudding user response:

Disregarding your template, why not simply calling

jq 'map(
  .patient = {name: .patientName, familyName: .patientFamilyName}
  | del(.patientName, .patientFamilyName)
)' data.json

Demo (For this, I corrected your input JSON according to a presumed typo described in my comment above)

  • Related