'How to update a value in a complex fhirBundle JSON?

Given a bewildering fhir document like https://raw.githubusercontent.com/Notarise-gov-sg/api-notarise-healthcerts/master/test/fixtures/v2/pdt_art_with_nric_unwrapped.json

I need to update the part the JSON from { "id": "NRIC-FIN", "value": "S9098989Z" } to { "id": "NRIC-FIN", "value": "foobar" } and then emit the whole JSON again with that change.

I just about know how to access the value.

const fs = require("fs");
let rawdata = fs.readFileSync("pdt_art_with_nric_unwrapped.json");
let art = JSON.parse(rawdata);

let nric = art.fhirBundle.entry
  .flatMap((entry) => entry.resource)
  .find((entry) => entry.resourceType === "Patient")
  .identifier.find((entry) => entry.id === "NRIC-FIN").value;

console.log(nric);

Though I am puzzled how to update this value since it's so difficult to access. Am I missing a trick? I don't want to use regex btw!



Solution 1:[1]

Instead of traversing the object manually you can use library like Jsonpath:

function replace() {
  data = JSON.parse(data);

  jsonpath.apply(data,
    '$.fhirBundle.entry[?(@.resource.resourceType == "Patient")].resource.identifier[?(@.id == "NRIC-FIN")].value',
    function(value) {
      document.body.innerHTML += `value=${value}<br>`;
      return 'foobar';
    });

  document.body.innerHTML += `updated JSON:<br> <pre>${JSON.stringify(data, undefined, 2)}</pre`;
}


let data =
  `{
  "id": "340139b0-8e92-4ed6-a589-d54730f52963",
  "version": "pdt-healthcert-v2.0",
  "type": "ART",
  "validFrom": "2021-08-24T04:22:36.062Z",
  "fhirVersion": "4.0.1",
  "fhirBundle": {
    "resourceType": "Bundle",
    "type": "collection",
    "entry": [
      {
        "fullUrl": "urn:uuid:ba7b7c8d-c509-4d9d-be4e-f99b6de29e23",
        "resource": {
          "resourceType": "Patient",
          "extension": [
            {
              "url": "http://hl7.org/fhir/StructureDefinition/patient-nationality",
              "extension": [
                {
                  "url": "code",
                  "valueCodeableConcept": {
                    "text": "Patient Nationality",
                    "coding": [
                      { "system": "urn:iso:std:iso:3166", "code": "SG" }
                    ]
                  }
                }
              ]
            }
          ],
          "identifier": [
            {
              "id": "PPN",
              "type": {
                "coding": [
                  {
                    "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
                    "code": "PPN",
                    "display": "Passport Number"
                  }
                ]
              },
              "value": "E7831177G"
            },
            { "id": "NRIC-FIN", "value": "S9098989Z" }
          ],
          "name": [{ "text": "Tan Chen Chen" }],
          "gender": "female",
          "birthDate": "1990-01-15"
        }
      },
      {
        "fullUrl": "urn:uuid:0275bfaf-48fb-44e0-80cd-9c504f80e6ae",
        "resource": {
          "resourceType": "Specimen",
          "subject": {
            "type": "Device",
            "reference": "urn:uuid:9103a5c8-5957-40f5-85a1-e6633e890777"
          },
          "type": {
            "coding": [
              {
                "system": "http://snomed.info/sct",
                "code": "697989009",
                "display": "Anterior nares swab"
              }
            ]
          },
          "collection": { "collectedDateTime": "2020-09-27T06:15:00Z" }
        }
      }     
    ]
  },
  
  "issuers": [
    {
      "id": "did:ethr:0xE39479928Cc4EfFE50774488780B9f616bd4B830",
      "revocation": { "type": "NONE" },
      "name": "SAMPLE CLINIC",
      "identityProof": {
        "type": "DNS-DID",
        "location": "donotverify.testing.verify.gov.sg",
        "key": "did:ethr:0xE39479928Cc4EfFE50774488780B9f616bd4B830#controller"
      }
    }
  ],
  "$template": {
    "name": "HEALTH_CERT",
    "type": "EMBEDDED_RENDERER",
    "url": "https://healthcert.renderer.moh.gov.sg/"
  }
}`

replace();
<script src="https://cdn.jsdelivr.net/npm/[email protected]/jsonpath.min.js"></script>

If you are flat out replacing values without any other logic, and in case if you decide to use RegEx, then you can use String.replace().

let data =
  `{  "identifier": [
            {
              "id": "PPN",
              "type": {
                "coding": [
                  {
                    "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
                    "code": "PPN",
                    "display": "Passport Number"
                  }
                ]
              },
              "value": "E7831177G"
            },
            { "id": "NRIC-FIN", "value": "S9098989Z" }
          ],
          "name": [{ "text": "Tan Chen Chen" }],
          "gender": "female",
          "birthDate": "1990-01-15"
        }
    }`

let targetId = 'NRIC-FIN';
let find = new RegExp(`(?<=${targetId}.*value":\\s*").*?(?=")`, 'ig');
data = data.replace(find, 'foobar');;
document.write(`<pre>${data}</pre>`);

Note: In the regular expression, I have used i flag for case insensitive search. Used g flag to replace all occurrences of the id. If the id is unique and there is going to be only one occurrence in entire .json file then don't use g flag.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1