Skip to content

Breaking changes in 6.0

Andrzej Skowroński edited this page Jan 16, 2025 · 38 revisions

Breaking changes

  • Removed the IDeepCopyable interface, which was previously implemented on our POCOs. Its methods are now accessible via extensions.
  • Removed IsResource from the FhirTypeAttribute. One can just check against the Resource subtype instead.
  • Renamed the IsNestedType parameter on FhirTypeAttribute to IsBackboneType to align with common FHIR jargon.
  • Removed the BackboneTypeAttribute class. One can use IsBackboneType (above), the type's name (that was in this attribute) is now the ClassMapping.Name.
  • Removed the DefinitionPath property of ClassMapping, since it is the same as the ClassMapping.Name for backbone types.
  • POCO's no longer implement IDictionary<string,object>. Although this sounded like a good idea, it did break frameworks and made the debuggers display resoures as dictionaries. The interface is also not enough to base serializers or validators on, so it's use is limited. Therefore, we decided to remove it. You can now use EnumerateElements() instead, or functions like TryGetValue() and SetValue and the indexer ([]).
  • Since we now have a standard way to dynamically navigate a POCO, we removed Base.Children and Base.NamedChildren properties, since these have overlapping functionalities. Note that there is an extension method Children() (obsolete) that you can use for backwards-compatibility.
  • The type of ElementDefinition.Constraint.RequirementsElement, ElementDefinition.Binding.DescriptionElement, ElementDefinition.Mapping.CommentElement and CapabilityStatement.Implementation.DescriptionElement have changed from Markdown to PrimitiveType. Set this property to Markdown to get the original behaviour. This change allows you to use the correct type depending on the version of FHIR you are writing against (which matters in e.g. FhirPath expressions that match against type).
  • The type of Attachment.SizeElement has changed from Integer64 to PrimitiveType. Set this property to Integer64 to get the original behaviour, but you should now assign the correct type (i.e. UnsignedInteger before R5) depending on the version of FHIR you are writing against.
  • The type of Bundle.Link.RelationElement has changed from FhirString to PrimitiveType. Set this property to Integer64 to get the original behaviour, but you can now use the correct type depending on the version of FHIR you are writing against.
  • The type of Meta.ProfileElement has changed from Canonical to Code. Set this property to Integer64 to get the original behaviour, but you can now use the correct type depending on the version of FHIR you are writing against.
  • Each of the above elements no have multiple helper properties (e.g. Attachment.Size and Attachment.SizeUnsignedInteger) to allow you to use "simple assignments" of primitives.
  • IAnnotatable now inherits IAnnotated, so implementers of the former will have to implement the latter. Which makes sense, since objects that can be annotated should provide support for reading those annotations too.
  • Resource.HasVersionId has been removed as part of a clean up of the public interface of Resource. Just check Resource.VersionId for null.
  • Resource.SyncLock has been removed, as this is not a responsibility for Resource, and lock objects will change in .NET 9.
  • The IDeepComparable interface has disappeared, the Matches() and IsExactly() functions now simply take a Base as parameter. Also, it is now possible to write new custom comparison operations using the new CompareChildren() function, given a custom implementation of IEqualityComparer<T>.
  • The [Bindable] attribute has been removed in favor of the more useful ICoded. So, if you want to determine whether a datatype can be bound to, you can check for ICoded, and then call its members to get to a coded representation of that datatype. This is also true for Resources, though that is normally only used in the context of CQL.
  • ISystemAndCode has been removed from Code<T>, it now implements the equivalent (but more general) ICoded, like all datatypes.

Breaking changes to the serializers

All the settings classes for serializers (FhirJson/XmlSerializationSettings, SerializerSettings, FhirJsonPocoSerializerSettings) have been taken out:

  • Pretty printing is not a configuration, but has returned as a parameter to serialization functions that produce a string or bytearray.
  • There is no longer a way to throw an exception if the serializer encounters an unknown element: this kind of "validation" is part of the parser and validator, and felt rather out of place in the serializer (which, by design, does not do any other kind of validation).
  • Summary filters can be passed as arguments to the serialization functions, since they are not a constant configuration option for a serializer, as the kind of summarization may vary from call to call to the serializer. This also meant removing the IncludeMandatoryElementsInSummary setting, as this should now be controlled by constructing a summary filter using SerializationFilter.ForSummary(), which has a parameter to control this setting. This filter is then passed as an argument to the serializer calls (or as an option to ForFhir()).
  • The ability to control trimming whitespace in XML values has been removed since the FHIR specification demands whitespace is always trimmed.
  • Most async versions of the serializers have been removed since we are using XmlWriter for Xml and have switched from Newtonsoft to System.Text.Json.Utf8JsonWriter internally, all of which have no support for async.
  • When configuring the System.Text.Json stack with ForFhir(), you no longer have to pass in separate serializer and deserializer option structures, they have both been combined into a single FhirJsonConverterOptions.
  • The BaseFhirPocoXml/JsonSerializer took a FhirRelease as a constructor argument, while all other multi-version classes (like BaseFhirClient) took a ModelInspector. We have made this consistent by letting the serializers have a ModelInspector argument.
  • The abstract base for all serializers, BaseFhirSerializer was not truely a useful baseclass for anything, it just contained some protected re-usable functions, that we have turned into (internal) extension methods. As part of cleaning up the deserializers and serializers, this class has been removed.
  • The new serializers implement stricter rules on encoding of special characters. While not a breaking change per se (the json is semantically equivalent after all), a character-by-character comparison of the outputs will not necessarily be the same (e.g. the + in timezones is being escaped). This is because we are using System.Text.Json's default encoder, not UnsafeRelaxedJsonEscaping.
  • Since we have combined the existing APIs of FhirXml/JsonSerializer and FhirXml/JsonPocoSerializer, we had to make the SummaryType parameter mandatory, to avoid ambiguous overloads. Similarly, we have renamed the optional root parameter for the XML serialization functions to rootName for consistency.
  • The serializer inheritance structure has been simplified, since there is no longer an "old" and "new" serializer, and now looks like this:
classDiagram
    BaseFhirXmlSerializer <|-- FhirXmlSerializer
    BaseFhirXmlSerializer <|-- BaseFhirXmlPocoSerializer
    BaseFhirXmlPocoSerializer <|-- FhirXmlPocoSerializer

    class BaseFhirXmlSerializer{
    }
    class FhirXmlSerializer{
    }
    class BaseFhirXmlPocoSerializer{
       << Obsolete >>
    }
    class FhirXmlPocoSerializer{
       << Obsolete >>
    }
Loading

Note that the "new" serializers are marked 'Obsolete', this is because their functionality has been moved to what used to be the old serializers (BaseFhirXmlSerializer/FhirXmlSerializer), so the obsolete messages will indicate that a rename is in place.

Removed obsolete members

  • ArtifactSummaryGenerator.Default has been removed, the constructor should be used instead.
  • Most synchronous versions of async extension methods on FhirClient have been removed. Those methods were just wrapping async calls, so the recommendation is to use Async version instead.
  • FhirClient.ExpandValueSet and FhirClient.ValidateCode have been marked as obsolete, async versions are recommended instead.
  • ClassMapping.IsNestedType has been removed, ClassMapping.IsBackboneType should be used to align with FHIR jargon.
  • VERSION_CONTENT_HEADER has been removed, VERSION_CONTENT_HEADER_NAME should be used instead.
  • ElementDefinition.Name has been removed, ElementDefinition.SliceName should be used instead.
  • FhirClientSettings.PreferredReturn has been removed, FhirClientSettings.ReturnPreference and/or FhirClientSettings.UseAsync instead.
  • FhirClientSettings.CompressRequestBody has been removed, FhirClientSettings.RequestBodyCompressionMethod instead.
  • FhirXmlException.ENCOUNTERED_DTP_REFERENCES_CODE has been removed as it had a typo, FhirXmlException.ENCOUNTERED_DTD_REFERENCES_CODE should be used instead.
  • Multiple constructors for FhirJsonPocoDeserializers have been removed, the default constructor should be used if a single version of FHIR is user, otherwise BaseFhirJsonPocoDeserializer should be used instead.
  • Multiple constructors for FhirXmlPocoDeserializer have been removed, the default constructor should be used if a single version of FHIR is user, otherwise BaseFhirXmlPocoDeserializer should be used instead.
  • HttpUtil.Prefer has been removed, HttpUtil.ReturnPreference should be used instead.
  • Lexer.Quantity has been removed as it's no longer used by FhirPath parser.
  • SearchParamDefinition.ComposityParams has been removed, SearchParamDefinition.Component should be used instead.
  • Element.RemoveAllConstrainedByDiffExtensions and IEnumerable<T>.RemoveAllConstrainedByDiffExtensions extensions have been removed, RemoveAllNonInheritableExtensions should be used instead.
  • TransactionBuilder.Create,TransactionBuilder.Update,TransactionBuilder.Patch,TransactionBuilder.Delete have been removed, the ConditionalCreate/ConditionalUpdate/ConditionalPatch/ConditionalDeleteSingle should be used instead.
  • ValidateEnumCodeAttribute has been removed, CodePatternAttribute should be used instead.
  • ValueSet.Define has been removed, the property has been renamed in DSTU2 standard and moved out in DSTU3.
  • ValueSetExpander.Expand has been removed, the asynchronous version should be used instead.
  • ZipSource.Source has been removed, the ZipSource implements the IConformanceSource so should be used directly.

Behavioural changes

  • We have archived the Fhir.Metrics library. This means that Types/Quantity no longer supports UCUM unit conversion. Comparing units will now only succeed if the units are equivalent, at which point they are compared by value.
  • Narrative.div and Narrative.status are no longer in-summary (to reflect corrections made to this effect in the FHIR spec). This will result in a different rendering of resources when generating summaries.
  • Code<T> is now a subclass of Code, which means you only have to check against Code to know you're dealing with a code. The Value property returns a string when treating it as a Code, and will return an enum value otherwise. This change in hierarchy means that the order of type matches may be influenced, checking a Code<T> against Code was not a match before, but is now. Note that the single value in Code<T> actually has an implicit code and system that are defined for that code, so conceptually Code<T> is more like a Coding.

Minor/exotic breaking changes

  • Parameters.this[] has been removed in favor of a (future) use of this operator on the base, e.g. for dynamic access to elements. You can use the existing (and equivalent) GetSingle() instead.
  • ReflectionHelper.IsTypedCollection(System.Type) has been renamed to ReflectionHelper.IsTypedList(System.Type) since checking against ICollection<T> is not sufficient anymore to determine whether an element's type is a List, so we check against IList<T> instead.
  • The type of FhirEvaluationContext.TerminologyService has been changed from ITerminologyService to ICodeValidationTerminologyService. For most users, this should not be breaking.
  • The WithResourceOverrides static method introduced in 5.10 is now an extension method (and will need to be called on an instance). This allows subclasses to inherit it without implementing it themselves.
  • Moved ScopedNodeExtensions from the ElementModel namespace to the Model namespace. Import Hl7.Fhir.Model when using methods like Resolve()
  • The type of FhirEvaluationContext.ElementResolver has been changed from Func<string, ITypedElement> to Func<string, IScopedNode>. External resolvers should make sure to return a scoped node.
  • The DefaultModelFactory has been removed. It had not been in use for years, except by our own tests. With the cleanup of the PocoBuilder (ITypedElement->POCO) infrastructure, we decided to remove this class.
  • CitedArtifactContributorshipSummaryComponent has been renamed to the more correct ContributorshipSummaryComponent.
Clone this wiki locally