fhir-types
Per-version FHIR types and terminology operation contracts.
Generated Rust types for the FHIR R4 (4.0.1), R4B (4.3.0), R5 (5.0.0), and R6
(6.0.0-ballot5) terminology surface: CodeSystem, ValueSet, ConceptMap,
Parameters, OperationOutcome, CapabilityStatement,
TerminologyCapabilities, Bundle, the datatypes and primitives they reach,
a JSON codec, and typed request and response contracts for $lookup,
$validate-code, $expand, $subsumes, and $translate per version, each
with a runtime descriptor of the declared parameter set. The resources
feature widens the same tree to every concrete resource each package defines,
with the complete closure of the datatypes those resources reference.
Features
One tree holds every type the generator emits, and the features select inside it. The default set is what a dependant gets with no feature list.
| Feature | What it enables | Default |
|---|---|---|
r4 |
the FHIR R4 (4.0.1) module | yes |
r4b |
the FHIR R4B (4.3.0) module | yes |
r5 |
the FHIR R5 (5.0.0) module | yes |
r6 |
the FHIR R6 (6.0.0-ballot5) module | yes |
terminology |
the terminology root set, the closure of the types it references, and the operation contracts | yes |
resources |
every concrete resource each package defines, with its complete closure; enables terminology |
no |
A version module carries only the types the enabled root set selects, so
default-features = false with r4 and terminology builds the R4
terminology surface alone. Resource holds one variant per resource the
enabled features select, and UnknownResource carries any other resource's
JSON body unchanged.
Every file is generated by fhir-codegen
from the vendored HL7 packages and marked // @generated. To change the
output, change the generator and regenerate; the crate is never hand-edited.
The terminology ecosystem overlay (the HL7 terminology ecosystem IG requirements)
is applied at generation and marked per parameter.
The element table
Each version module carries schema::SCHEMAS, the elements of every type it
emits in definition order. Per element it holds the ElementDefinition path,
min, max, the type codes the definition lists, the contentReference
target, and the kind the XML codec reads. Schemas::element resolves a dotted
element path through complex types, backbone elements and content references,
and answers on a choice element's base path and on each expanded form the JSON
representation gives it; Schemas::type_of gives the type a path resolves to.
use SCHEMAS;
let = SCHEMAS
.element
.expect;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
A type the enabled features leave out is absent from the table, so a path into
it resolves to None.
JSON and decimal precision
The codec reads and writes FHIR JSON through its own document model,
fhir_types::codec::Value, which holds a number in the text the document
carried. FHIR says "Do not use an IEEE type floating point type, instead use
something that works like a true decimal"
(https://hl7.org/fhir/R4B/datatypes.html#decimal), so 1.10 keeps its
trailing zero and a decimal past f64 precision keeps its digits, through the
Serialize impls and through Json::to_json alike.
That costs a dependent nothing. The crate turns on no serde_json feature that
changes how numbers deserialize, so your own types keep reading and writing the
JSON they always did. Reading a document uses serde_json's raw value, so the
Deserialize impls read serde_json's format.
Converting to and from serde_json::Value
A decimal is never silently altered, so the conversion out is fallible.
Value::into_serde_json and Value::to_serde_json hand the document to
serde_json only when every number comes back in the text the document
carried; a number serde_json would write differently, or cannot hold at all,
is a ValueConversionError naming the element path
(Observation.valueQuantity.value), the lexical form and what serde_json
writes. With arbitrary_precision on your side every form converts; without
it, whole numbers and the decimals f64 writes back convert and 1.50 is
refused.
Value::from_serde_json is the other direction and cannot fail. It takes the
number in the text serde_json holds, which is the document's own form under
arbitrary_precision and the f64 rendering of it otherwise, so read a
document whose decimals must stay exact through this crate's decoder
(serde_json::from_str::<fhir_types::codec::Value>) rather than through
serde_json::Value.
Where it sits
fhir-types is generated in FerroBRIDGE,
a pure-Rust bridge between openEHR and HL7 FHIR and the OMOP Common Data Model.
The crate is published so other projects can reuse it; the API is pre-1.0 and
moves with the FerroBRIDGE release train. Documentation:
https://docs.rs/fhir-types.
Licence
Apache License, Version 2.0 (LICENSE). This is the one first-party crate the
workspace publishes under Apache 2.0 rather than its Business Source License
1.1, so any Rust project can depend on it without a licence conversation. Clinical terminology content (SNOMED
CT, LOINC, RxNorm, ICD, the Dutch national code systems) is licensed by its
publisher and is never part of this crate.