Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect handling of whitespace when using the JSON serializer #2661

Closed
tkallsen opened this issue Jan 10, 2024 · 9 comments · Fixed by #2723
Closed

Incorrect handling of whitespace when using the JSON serializer #2661

tkallsen opened this issue Jan 10, 2024 · 9 comments · Fixed by #2723
Assignees

Comments

@tkallsen
Copy link

Describe the bug
The Firely SDK trims whitespace when using the JSON serializer, which is not according to spec. This is a big problem when connecting to a FHIR server that treats leading/trailing whitespace as significant. It is only for XML that there is a recommendation to trim whitespace.

Additionally, for the XML serializer there exists an option to turn of whitespace trimming by setting SerializerSettings.TrimWhiteSpacesInXml to false.

To Reproduce

var serializer = new FhirJsonSerializer();
var patient = new Patient { Name = new List<HumanName> { new HumanName { Family = " Smith " } } };
var json = await serializer.SerializeToStringAsync(patient);
Assert.IsTrue(json.Contains(" Smith "));`

Expected behavior
Whitespace should not be trimmed by default when using JSON serialization since that is not part of the spec. But since this would be a breaking change it could instead be implemented as an option, TrimWhiteSpacesInJson, not to trim whitespace, like the existing TrimWhiteSpacesInXml property (with a default value of true).

Version used:

  • FHIR Version: R4 (generic)
  • Version: 4.3.0 / 5.4.1 (tested)

Additional context
Robert B has been in contact with you through e-mail.

If desired I can provide a PR.

@ewoutkramer
Copy link
Member

Indeed, we carefully redid the whitespace handling when we wrote the new serializers (well, they are 3+ years old now, have to stop calling them new), which are described here. The new json serializer will not trim your strings anymore, so that's the most easy way to fix this problem!

@tkallsen
Copy link
Author

Alright, yes, that works as long as we can upgrade to 5.5.0. Thank you!

@tkallsen
Copy link
Author

Hi,

unfortunately I have to reopen this case. A typical operation for us would be to GET a MedicationRequest, change a property, and then PUT the changed MedicationRequest back to the source server.

If we do this, the POCO-serializer in 5.5.0 will not strip whitespace. However, the deserialization of the GET/MedicationRequest call will trim strings, through FhirJsonNode:

public string Text
{
    get
    {
        if (JsonValue != null)
        {
            if (JsonValue.Value != null)
            {
                // Make sure the representation of this Json-typed value is turned
                // into a string representation compatible with the XML serialization
                return JsonValue.Value is string s ? s.Trim()
                    : PrimitiveTypeConverter.ConvertTo<string>(JsonValue.Value);
            }
        }

        return null;
    }
}

So our PUT/update call will still send trim:ed strings to the server. Is there a way around this?

@mmsmits
Copy link
Member

mmsmits commented Jan 19, 2024

It's true that the FhirClient will use the legacy validators by default (so users didn't get any unexpected changes when upgrading)

However, you can alter this as mentioned here: https://docs.fire.ly/projects/Firely-NET-SDK/en/latest/client/setup.html#selecting-a-serializer

If you choose one of the non-legacy serializer modes, this will be solved and FhirJsonNode will not be used.

Hope this solves your issue!

@tkallsen
Copy link
Author

Do you have an example of how to do this when using the FhirClient?

This is basically what we are currently using with 5.5:

var fhirClient = new FhirClient(someRemoteAddress, messageHandler: someFhirMessageHandler);
fhirClient.Settings.PreferredFormat = ResourceFormat.Json;
fhirClient.Settings.ReturnPreference = ReturnPreference.OperationOutcome;
fhirClient.Settings.SerializationEngine = FhirSerializationEngineFactory.Strict(ModelInfo.ModelInspector);

And the FhirClient is then used when deserializing.

@mmsmits
Copy link
Member

mmsmits commented Jan 19, 2024

These settings seem correct and should not trim your whitespaces.
We should investigate what's going on and try to reproduce this.

@tkallsen
Copy link
Author

I think I have found the problem. If you set the serialization engine in the FhirClient constructor via a settings object, everything works. If you set the engine through the SerializationEngine property after FhirClient object creation, it won't be picked up:

 var fieldInfo = typeof(BaseFhirClient).GetField("_serializationEngine", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

 var fhirClient1 = new FhirClient(
     "http://example.com",
     settings: new FhirClientSettings { SerializationEngine = FhirSerializationEngineFactory.Strict(ModelInfo.ModelInspector) }
 );

 Assert.AreEqual(typeof(PocoSerializationEngine), fieldInfo.GetValue(fhirClient1).GetType());


 var fhirClient2 = new FhirClient(
     "http://example.com"
 );
 fhirClient2.Settings.SerializationEngine = FhirSerializationEngineFactory.Strict(ModelInfo.ModelInspector);

 // Fail, serialization engine is ElementModelSerializationEngine here
 Assert.AreEqual(typeof(PocoSerializationEngine), fieldInfo.GetValue(fhirClient2).GetType());

I would call this a bug, since other Settings-properties are correctly picked up even if changed later (but with an easy workaround to just send in the serialization engine in the constructor).

@ewoutkramer
Copy link
Member

Thanks for hunting this down, that helps!

@Kasdejong Kasdejong self-assigned this Feb 20, 2024
mmsmits added a commit that referenced this issue Feb 21, 2024
…alizer-settings

#2661 FhirClient Serialization engine modification
@mmsmits mmsmits linked a pull request Feb 21, 2024 that will close this issue
@mmsmits
Copy link
Member

mmsmits commented Feb 21, 2024

Closed by #2661

@mmsmits mmsmits closed this as completed Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants