# FHIR extensions

Read and write the fields the base specification does not define, including complex extensions that nest further extensions inside.

You can read and write extensions - the fields the base specification does not define. Real-world data always includes some: a patient's birth place, their preferred pharmacy, attributes required by a national Implementation Guide. FHIR stores all of it in `extension`, a list that any resource or element can contain, where each entry is identified by a URL and holds one typed value.

## What an extension looks like {#what-an-extension-looks-like}

An extension is plain data, e.g. a Patient with a birth place looks like this on the wire:

```json
{
  "resourceType": "Patient",
  "extension": [
    {
      "url": "http://hl7.org/fhir/StructureDefinition/patient-birthPlace",
      "valueAddress": {"city": "Amsterdam", "country": "NL"}
    }
  ]
}
```

## Read extensions {#read-extensions}

Because the order of the extension list is never guaranteed, read extensions by their URL with a [path matcher](https://zato.io/docs/dev/healthcare/hl7/fhir/path-access/index.html) rather than by index:

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

birth_place_url = 'http://hl7.org/fhir/StructureDefinition/patient-birthPlace'

class ReadBirthPlace(Service):
    name = 'demo.fhir.read-birth-place'

    def handle(self) -> 'None':

        client = self.fhir['FHIR.Sample']
        patient_id = '511a6231-361e-4b8e-8f9c-b183b7813f4d'
        patient = client.resources('Patient').search(_id=patient_id).get()

        # Select the extension by its URL and read the city from its value
        path = ['extension', {'url': birth_place_url}, 'valueAddress', 'city']
        city = patient.get_by_path(path)

        self.logger.info('Born in %s', city)
```

## Nested extensions {#nested-extensions}

Implementation Guides often define complex extensions whose value is a further list of sub-extensions. The standard patient-nationality extension is one - the outer extension has no value of its own, only inner ones:

```json
{
  "url": "http://hl7.org/fhir/StructureDefinition/patient-nationality",
  "extension": [
    {"url": "code", "valueCodeableConcept": {"text": "Dutch"}},
    {"url": "period", "valuePeriod": {"start": "2004-05-01"}}
  ]
}
```

The path follows the nesting of the data, with a matcher at each extension level:

```python
nationality_url = 'http://hl7.org/fhir/StructureDefinition/patient-nationality'

# From the outer extension by URL, into the inner one by URL, down to the value
path = [
    'extension', {'url': nationality_url},
    'extension', {'url': 'code'},
    'valueCodeableConcept', 'text',
]
nationality = patient.get_by_path(path)
```

## Write extensions {#write-extensions}

To add an extension, append to the resource's extension list - creating the list first if the resource has none - and save:

```python
# The resource may not have any extensions yet
if 'extension' not in patient:
    patient.extension = []

# Add the new one ..
patient.extension.append({
    'url': birth_place_url,
    'valueAddress': {'city': 'Amsterdam', 'country': 'NL'}
})

# .. and persist the change.
patient.save()
```

To replace an existing extension, filter it out by its URL first so the list never holds duplicates:

```python
patient.extension = [item for item in patient.extension if item['url'] != birth_place_url]

patient.extension.append({
    'url': birth_place_url,
    'valueAddress': {'city': 'Rotterdam', 'country': 'NL'}
})

patient.save()
```

## See also {#see-also}

- [Path access](https://zato.io/docs/dev/healthcare/hl7/fhir/path-access/index.html) - Dotted paths, list indexes and the matchers used above
- [Resources](https://zato.io/docs/dev/healthcare/hl7/fhir/resources/index.html) - Create, read, update and delete any FHIR resource
- [FHIR in Europe](https://zato.io/docs/dev/healthcare/hl7/fhir/europe/index.html) - The national programs whose guides define extensions

## Learn more {#learn-more}

- [Healthcare interface engine](https://zato.io/docs/dev/healthcare/) - Clinical messages, FHIR, conversion and operations
- [HL7 v2 parsing](https://zato.io/docs/dev/healthcare/hl7/v2/parsing/) - Messages as typed objects, with field access and validation
- [MLLP channels](https://zato.io/docs/dev/healthcare/hl7v2/mllp/) - Receiving and sending HL7 v2 over MLLP sockets
- [FHIR integrations](https://zato.io/docs/dev/healthcare/hl7/fhir/) - Read and write FHIR resources, with paths, bundles and extensions
- [HL7 v2 to FHIR](https://zato.io/docs/dev/healthcare/hl7/to-fhir/) - Converting v2 messages into FHIR bundles, codes and references included
- [EDIFACT](https://zato.io/docs/dev/healthcare/edifact/) - Parsing interchanges, dialects and the transports they arrive on
- [Transformation](https://zato.io/docs/dev/healthcare/transformation/) - One message in, another standard out, in ordinary Python
- [Audit log](https://zato.io/docs/dev/healthcare/audit-log.html) - Every message with its acknowledgment, searchable by patient identifier
- [AI in clinical interfaces](https://zato.io/docs/dev/healthcare/ai/) - Services calling LLMs and AI agents calling clinical services as tools
