diff --git a/src/Hl7.Fhir.Shims.Base/Specification/Terminology/ValueSetExpander.cs b/src/Hl7.Fhir.Shims.Base/Specification/Terminology/ValueSetExpander.cs index 7fbb0b442..d44cc81ba 100644 --- a/src/Hl7.Fhir.Shims.Base/Specification/Terminology/ValueSetExpander.cs +++ b/src/Hl7.Fhir.Shims.Base/Specification/Terminology/ValueSetExpander.cs @@ -383,7 +383,7 @@ internal static ValueSet.ContainsComponent ToContainsComponent(this CodeSystem.C if (inactiveProperty?.Value is FhirBoolean isInactive) newContains.Inactive = isInactive.Value; -#if !STU3 +#if !(STU3 || R4) if (source.Property.Any()) { newContains.Property = source.Property.Select(p => new ValueSet.ConceptPropertyComponent { Code = p.Code, Value = p.Value }).ToList(); diff --git a/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs b/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs index 0d2d82f00..17325645f 100644 --- a/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs +++ b/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs @@ -1,6 +1,7 @@ using FluentAssertions; using Hl7.Fhir.Model; using Hl7.Fhir.Rest; +using Hl7.Fhir.Serialization; using Hl7.Fhir.Specification.Source; using Hl7.Fhir.Specification.Terminology; using Hl7.Fhir.Validation; @@ -762,6 +763,54 @@ void expandAction(string url) } } + /// + /// Test for issue with ValueSet expansion causing NullReferenceException during serialization + /// when the expansion contains property field that doesn't exist in R4/R4B. + /// The Property field in ValueSet.expansion.contains was introduced in R5. + /// Uses item-type ValueSet which has properties in R5. + /// + [Fact] + public async Tasks.Task ExpandedValueSetShouldSerializeSuccessfully() + { + var server = new LocalTerminologyService(_resolver); + var parameters = new Parameters() + { + Parameter = new List + { + new Parameters.ParameterComponent() + { + Name = "url", + Value = new FhirUri("http://hl7.org/fhir/ValueSet/item-type"), + }, + }, + }; + + var resource = await server.Expand(parameters); + + // This should not throw a NullReferenceException + var json = resource.ToJson(); + + // Verify the expansion was successful + Assert.NotNull(json); + Assert.NotEmpty(json); + var valueSet = resource as ValueSet; + Assert.NotNull(valueSet); + Assert.True(valueSet.HasExpansion); + Assert.True(valueSet.Expansion.Contains.Any()); + +#if R5 || R6 + // In R5 and R6, verify that the Property element is correctly set in the expansion + // when the CodeSystem has properties defined. The item-type CodeSystem has the + // "notSelectable" property defined for some concepts (e.g., "question"). + var containsWithProperties = valueSet.Expansion.Contains + .Where(c => c.Property != null && c.Property.Any()) + .ToList(); + + // The item-type ValueSet should have at least one concept with properties in R5+ + Assert.NotEmpty(containsWithProperties); +#endif + } + [Fact] public void TestValidateCodeParametersCode() {