-
Notifications
You must be signed in to change notification settings - Fork 357
Description
Describe the bug
Our developers sometimes adds null Extension objects inside Extensions list.
var patient = new Patient { Id = "example" };
patient.Extension = [null, new("http://test", new FhirString("abcd"))];
// Expected json: {"resourceType": "Patient", "id": "example", "extension": [{"url":"http://test", "valueString": "abcd"}]}
// Wrong json: {"resourceType": "Patient", "id": "example", "extension": [null, {"url":"http://test", "valueString": "abcd"}]}When we used the Newtonsoft.Json serializer, this would be automatically be set ignored during serialization, but using the SystemTextJson serializer prior to SDK 6, we added a custom SerializationFilter that would filter out these nulls,
sealed class NullIgnoringSerializationFilter(SerializationFilter? original) : SerializationFilter
{
public override void EnterObject(object value, ClassMapping? mapping)
=> original?.EnterObject(value, mapping);
public override void LeaveMember(string name, object value, PropertyMapping? mapping)
=> original?.LeaveMember(name, value, mapping);
public override void LeaveObject(object value, ClassMapping? mapping)
=> original?.LeaveObject(value, mapping);
public override bool TryEnterMember(string name, object value, PropertyMapping? mapping)
{
if (value is IList collection)
{
while (collection.Contains(null))
{
collection.Remove(null!);
}
}
return original?.TryEnterMember(name, value, mapping) ?? true;
}
}However when tested with SDK6, whenever a null is encountered in a list, this exception always shows up:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at Hl7.Fhir.Model.BaseExtensions.DeepCopy[T](T source)
at Hl7.Fhir.Model.BaseExtensions.<>c__8`1.<DeepCopyInternal>b__8_0(T item)
at System.Linq.Enumerable.SelectListIterator`2.Fill(ReadOnlySpan`1 source, Span`1 destination, Func`2 func)
at System.Linq.Enumerable.SelectListIterator`2.ToList()
at Hl7.Fhir.Model.BaseExtensions.DeepCopyInternal[T](IEnumerable`1 source)
at Hl7.Fhir.Model.DomainResource.CopyToInternal(Base other)
at Hl7.Fhir.Model.Patient.CopyToInternal(Base other)
at Hl7.Fhir.Model.Patient.DeepCopyInternal()
at Hl7.Fhir.Model.BaseExtensions.DeepCopy[T](T source)
at Hl7.Fhir.Utility.SerializationUtil.MakeSubsettedClone(Base source)
at Hl7.Fhir.Serialization.BaseFhirJsonSerializer.Serialize(Base instance, Utf8JsonWriter writer, Func`1 filterFactory)
at Hl7.Fhir.Serialization.FhirJsonConverter`1.Write(Utf8JsonWriter writer, TF poco, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed)
at System.Text.Json.JsonSerializer.WriteString[TValue](TValue& value, JsonTypeInfo`1 jsonTypeInfo)
at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
at Program.<Main>$(String[] args) in D:\repos\FhirSerializationTest\FhirSerializationTest\Program.cs:line 16
I asked our developers to avoid these null list members in the future. Also, it would be good if the serializer can automatically ignore these null members without having to write a serialization filter, or at least, honor the JsonSerializerOptions.DefaultIgnoreCondition when it is set to JsonIgnoreCondition.WhenWritingDefault.
Versions used:
6.0.1, 5.12.2