Janus
0.1.1 - ci-build
Janus - Local Development build (v0.1.1) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
A StructureMap is a FHIR resource that defines rules for transforming data from one structure to another. It is commonly used to map data between different FHIR resource types or between FHIR and other data formats, leveraging a Mapping Service to facilitate these conversions. StructureMaps use a domain-specific language to describe how source data should be interpreted and converted into a target structure, supporting complex transformations, conditional logic, and value mappings.
StructureMaps are essential for interoperability, enabling seamless data exchange and migration across healthcare systems.
For more information, refer to the FHIR StructureMap specification.
A StructureMap resource includes metadata that describes its identity, versioning, status, and purpose. These elements help manage, reference, and document your mapping logic.
resourceType: Always "StructureMap".id: Unique identifier for the StructureMap instance.meta: Versioning and provenance (versionId, lastUpdated, source).url: Canonical URL for referencing the StructureMap.version: Version number of the StructureMap.name: Machine-friendly name.title: Human-readable title.status: Publication status (draft, active, etc.).description: Detailed explanation of the StructureMap's purpose and usage.Example:
{
// The type of FHIR resource (always "StructureMap")
"resourceType": "StructureMap",
// Unique identifier for this StructureMap instance
"id": "StructureMap-QuestionnaireResponse-JSON",
// Metadata about versioning and provenance automatically generated
"meta": {
// Internal version number for this resource
"versionId": "28",
// Timestamp of last update
"lastUpdated": "2025-07-31T13:18:08.062+00:00",
// Reference to the source of this resource
"source": "#bd3DmG56zVdJCqXE"
},
// Canonical URL for referencing this StructureMap
"url": "https://www.isis.com/StructureMap/StructureMap-QuestionnaireResponse-JSON",
// Human-readable version number
"version": "1.0.1",
// Machine-friendly name for the StructureMap
"name": "TransformeQuestionnaireResponseJSONEnQuestionnaireRepsonseFHIRSDC",
// Human-readable title
"title": "Transforme une extraction JSON QuestionnaireResponse vers un FHIR SDC QuestionnaireResponse",
// Publication status (e.g., draft, active)
"status": "draft",
// Description of the StructureMap's purpose and usage
"description": "StructureMap permettant la transformation d'une extraction JSON de QuestionnaireResponse vers le standard FHIR SDC QuestionnaireResponse."
}
The structure element defines the resource types involved in the mapping. Each entry specifies the source or target structure, its canonical URL, and an optional alias.
url: Canonical URL of the resource structure (e.g., FHIR profile or resource).mode: Indicates if the structure is a source or target.alias: Optional short name used in mapping rules.Example:
"structure": [
// Source structure: custom QuestionnaireResponse profile
{
"url": "https://www.isis.com/StructureDefinition/LM-QuestionnaireResponse",
"mode": "source",
"alias": "source"
},
// Source structure: FHIR Questionnaire
{
"url": "http://hl7.org/fhir/StructureDefinition/Questionnaire",
"mode": "source",
"alias": "source"
},
// Target structure: FHIR SDC QuestionnaireResponse
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse",
"mode": "target",
"alias": "target"
}
]
The source element in a StructureMap defines the input data that will be transformed. This is the starting point for any mapping operation, and its configuration is crucial for successful data conversion. The source can represent various formats, such as FHIR resources, XML, JSON, CSV, or HL7v2, depending on your integration needs.
Note: The source element is read-only during the mapping process—it cannot be changed or modified. All transformation logic operates on the source data as provided. In contrast, the output (target) structure is created and populated by the mapping rules and will typically change as a result of the transformation.
group.input section.name: a unique identifier for the source input (e.g., "source", "questionnaire").type: usually a FHIR resource type (e.g., "Questionnaire", "Patient"), but you can also use generic formats such as "XML", "JSON", "CSV", or "HL7v2" if your mapping operates on non-FHIR data.mode: the role of the input, "source" for input data.Example:
{
"name": "source",
// FHIR resource type
"type": "Questionnaire",
"mode": "source"
}
or
{
"name": "source",
// Generic format
"type": "XML",
"mode": "source"
}
To transform XML data, you typically provide your source as a FHIR Binary resource containing the XML content. In your StructureMap, you reference the source type as XML:
Binary resource containing the XML source data:
{
"resourceType": "Binary",
"id": "EXP-BinaryTransformInput",
"contentType": "application/xml",
"data": "PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxRdWVyeT4uLi48L1F1ZXJ5Pg=="
}
StructureMap group referencing XML as source:
"group": [
{
"name": "main",
"input": [
// Source input: XML data to be transformed
{
"name": "source",
"type": "XML",
"mode": "source"
}
]
}
]
It is possible to define multiple sources in a StructureMap, each representing a different input required for the transformation. This is especially useful for complex mappings, such as converting a custom Questionnaire response format to a FHIR QuestionnaireResponse using a FHIR Questionnaire as a reference.
Typical scenario:
How to define multiple sources:
group.input section, you declare each source with its type and mode.Example:
"group": [
{
"name": "main",
"input": [
// Source 1: Custom response data (e.g., client's JSON)
{
"name": "responseSource",
"type": "JSON",
"mode": "source"
},
// Source 2: FHIR Questionnaire (not populated)
{
"name": "questionnaireSource",
"type": "Questionnaire",
"mode": "source"
}
]
}
]
Frontend/Backend:
This approach enables advanced mappings, such as merging data from different origins or formats, and is essential for workflows like questionnaire extraction and response generation.
The target element in a StructureMap defines the structure that will receive the transformed data. This is where the mapping engine writes the output after applying the transformation rules. The target represents the final output format of your transformation, but you can also define intermediate targets within the mapping process.
group.input section.name: a unique identifier for the target input (e.g., "target", "output").type: usually a FHIR resource type (e.g., "Bundle", "ServiceRequest", "QuestionnaireResponse"), but you can also use generic formats such as "CSV", "JSON", or "XML" if your mapping produces non-FHIR output.mode: the role of the input, "target" for output data.Example:
{
"name": "target",
// FHIR resource type
"type": "Bundle",
"mode": "target"
}
or
{
"name": "target",
// Generic format
"type": "CSV",
"mode": "target"
}
Here is a StructureMap group that defines both source and target inputs, following the same format as the source section:
"group": [
{
"name": "main",
"input": [
// Source input: e.g., XML data to be transformed
{
"name": "source",
"type": "XML",
"mode": "source"
},
// Target input: FHIR Bundle to receive the transformed data
{
"name": "target",
"type": "Bundle",
"mode": "target"
}
]
}
]
In more complex mappings, you may need to work with intermediate targets during the transformation process. For example, when transforming a custom questionnaire response to a FHIR QuestionnaireResponse, the mapping rules may first populate a non-completed QuestionnaireResponse (intermediate target) before producing the final, fully populated QuestionnaireResponse (output).
Important:
Only the final target (the resource to be returned as output) is declared in the group.input section. Intermediate targets are not declared as separate inputs; they are managed and populated within the mapping rules using variables and context references.
Example:
"group": [
{
"name": "main",
"input": [
// Target input: FHIR QuestionnaireResponse to be populated and returned as output
{
"name": "target",
"type": "QuestionnaireResponse",
"mode": "target"
}
]
}
]
How it works:
This approach supports advanced scenarios, such as generating multiple FHIR resources or handling intermediate outputs, and ensures flexibility for various healthcare data transformation workflows.
After the transformation, the output is typically returned as a FHIR Binary resource. The data field contains the result (e.g., a FHIR QuestionnaireResponse in JSON format), encoded in base64.
Example:
{
"resourceType": "Binary",
"id": "EXP-BinaryTransformOutput",
"contentType": "application/json",
"data": "ewogICJxdWVzdGlvbm5haXJlUmVzcG9uc2UiOiB7CiAgICAiaWRlbnRpZmllciI6ICIxMjM0NSIsCiAgICAic3ViamVjdCI6IHsKICAgICAgInJlZmVyZW5jZSI6ICJQYXRpZW50LzY3ODkwIgogICAgfQogIH0KfQ=="
}
This example represents a QuestionnaireResponse output with an identifier and subject, encoded in base64.
You can decode the data field to view the actual JSON result:
{
"questionnaireResponse": {
"identifier": "12345",
"subject": {
"reference": "Patient/67890"
}
}
}
StructureMap rules define how data is mapped from source to target elements. Each rule specifies:
Rules are organized in the group.rule section and can be nested for complex mappings.
A rule typically contains:
name: The rule's identifier.source: The source context, type, element, and variable.target: The target context, element, transformation, and parameters.condition, min, max, and nested rule for sub-mappings.Example (JSON to FHIR Patient):
"rule": [
{
"name": "nom",
"source": [
{
"context": "patientExtract",
"min": 1,
"max": "1",
"type": "string",
"element": "nom",
"variable": "nom"
}
],
"target": [
{
"context": "targetPatient",
"contextType": "variable",
"element": "name.family",
"transform": "copy",
"parameter": [
{
"valueId": "nom"
}
]
}
],
"rule": []
}
]
element field uses HL7v2 segment notation (e.g., "NK1-2-2" for the second field of the second NK1 segment)."rule": [
{
"name": "firstName",
"source": [
{
"context": "source",
"type": "string",
"element": "NK1-2-2",
"variable": "firstName0"
}
],
"target": [
{
"context": "targetPatient",
"contextType": "variable",
"element": "name.given",
"transform": "copy",
"parameter": [
{
"valueId": "firstName0"
}
]
}
],
"rule": []
}
]
element field refers to the column name or index in the CSV file."rule": [
{
"name": "csvColumn",
"source": [
{
"context": "source",
"type": "string",
"element": "columnA",
"variable": "valueA"
}
],
"target": [
{
"context": "targetPatient",
"contextType": "variable",
"element": "identifier.value",
"transform": "copy",
"parameter": [
{
"valueId": "valueA"
}
]
}
],
"rule": []
}
]
element field refers to the property name in the JSON object."rule": [
{
"name": "prenom",
"source": [
{
"context": "source",
"type": "string",
"element": "prenom",
"variable": "prenom"
}
],
"target": [
{
"context": "targetPatient",
"contextType": "variable",
"element": "name.given",
"transform": "copy",
"parameter": [
{
"valueId": "prenom"
}
]
}
],
"rule": []
}
]
Rules can be nested to handle complex structures, such as repeating groups, conditional mappings, or multiple targets.
Example (Multiple Targets):
"rule": [
{
"name": "age",
"source": [
{
"context": "patientExtract",
"type": "integer",
"element": "age",
"variable": "age"
}
],
"target": [
{
"context": "targetObservationAge",
"element": "value",
"transform": "cast",
"parameter": [
{ "valueId": "age" },
{ "valueString": "integer" }
]
}
],
"rule": [
{
"name": "ageCategory",
"source": [
{
"context": "patientExtract",
"type": "string",
"element": "ageCategory",
"variable": "ageCategory"
}
],
"target": [
{
"context": "targetObservationCatAge",
"element": "value",
"transform": "copy",
"parameter": [
{ "valueId": "ageCategory" }
]
}
],
"rule": []
}
]
}
]
element Field"PID-5-1").structure section with your source and target formats.group.input section, define the source input with its type and mode.element property to specify which part of the source data to map.group.rule section.By following these steps and understanding the role of the source element, frontend, backend, and Binary resource, anyone can create and execute a StructureMap for healthcare data transformation.