Serialization
Serialization turns a POCO back into FHIR JSON or XML. The types below live in:
using Hl7.Fhir.Serialization;
Note
Serialization does not validate the POCO — it faithfully writes whatever the object contains, even if that produces invalid FHIR. This is intentional (it allows round-tripping imperfect data and avoids duplicate work), but it means that if you need guaranteed-valid output you should validate the instance first.
Choosing a serializer
For a single FHIR version, use the ready-made FhirJsonSerializer.Default or FhirXmlSerializer.Default:
var json = FhirJsonSerializer.Default.SerializeToString(patient);
For a custom or runtime-chosen model, construct a BaseFhirJsonSerializer / BaseFhirXmlSerializer with a ModelInspector (see the ModelInspector):
var serializer = new BaseFhirJsonSerializer(inspector);
Output formats
Serializers produce a string, a UTF-8 byte array, or a document object, and can also write straight to a writer:
string json = FhirJsonSerializer.Default.SerializeToString(patient);
byte[] utf8 = FhirJsonSerializer.Default.SerializeToBytes(patient);
JObject doc = FhirJsonSerializer.Default.SerializeToDocument(patient);
FhirJsonSerializer.Default.Serialize(patient, utf8JsonWriter);
Pass pretty: true for indented output (compact is the default):
var json = FhirJsonSerializer.Default.SerializeToString(patient, pretty: true);
Summaries
FHIR defines summary forms of a resource — reduced views that contain only certain elements. The simplest way to produce one is to pass a SummaryType to SerializeToString, optionally restricting to specific top-level elements:
var summary = FhirJsonSerializer.Default.SerializeToString(patient, SummaryType.Text);
Under the hood a summary is a SerializationFilter. You can also create one directly and pass it as a factory to the serializer; the standard filters are available as factory methods:
Summary type |
Factory method |
|---|---|
|
|
|
|
|
|
|
|
|
|
The only other value the FHIR _summary parameter defines is false, meaning the complete resource — that is just ordinary serialization, with no filter.
var json = FhirJsonSerializer.Default.SerializeToString(
patient, filterFactory: () => SerializationFilter.ForSummary());
The filters are highly configurable, and you can write your own by subclassing SerializationFilter. For inspiration, see the (fairly simple) built-in implementations such as ElementMetadataFilter.cs and BundleFilter.cs in the SDK source.
Convenience extensions
For one-off calls you can skip creating a serializer and use the extension methods on any POCO, which use the default serializer for your FHIR version:
string json = patient.ToJson(pretty: true);
string xml = patient.ToXml();
ToJsonBytes, ToXmlBytes and ToXDocument are available too.
XML
Everything above applies to XML through FhirXmlSerializer / BaseFhirXmlSerializer; SerializeToDocument returns an XDocument, and Serialize takes an XmlWriter:
var xml = FhirXmlSerializer.Default.SerializeToString(patient, pretty: true);
When you serialize a datatype rather than a resource, the XML serializer wraps it in an element named after the type — for example a HumanName becomes <HumanName>…</HumanName>.
Experimental
As with deserialization, serializing a standalone datatype is outside the FHIR specification (which only defines serialization for resources) and should be treated as experimental. In particular, a lone FHIR primitive has no faithful representation — see Deserialization.
Advanced: customizing primitive serialization
You can change how primitive values are written to JSON by subclassing BaseFhirJsonSerializer and overriding SerializePrimitiveValue:
protected override void SerializePrimitiveValue(object? value, Utf8JsonWriter writer)
{
// custom handling, then fall back to the base implementation
base.SerializePrimitiveValue(value, writer);
}
A typical reason is precision: System.Text.Json only writes numbers that fit in a .NET decimal, which can be less precise than FHIR allows for very large decimals; an override can write such values as raw JSON instead.
Note
This hook applies when you use the serializer classes directly. It is not used by the System.Text.Json ForFhir converter, which creates its own serializer internally.
