-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Support the Specified convention for serializing and deserializing in System.Text.Json #40395
Comments
We have a use-case where we receive import data in JSON form, where the JSON schema supports many fields, but clients usually only send some fields. It's crucial we know which fields are present and which aren't, and neither defaults nor nulls work for this. With Newtonsoft.Json this was a breeze. But migrating to System.Text.Json is a real headache! Right now, we can get away by setting the Specified properties in the property setters (lots of code bloat), but it's no longer possible to reserialize/roundtrip back to JSON. This is related to #593 and #50294. Note that System.Xml and Newtonsoft.Json also support an additional variant via a The Specified convention is both for serialization, to emit/omit properties, and deserialization, to flag which properties were present in the payload. The It looks fairly simple to add this support to |
What benefits would such a convention provide over the using existing |
@eiriktsarpalis Also, |
Another generic option would be to have a special value undefined besides the special value null. This of course requires a major change for .Net CLI and is probably not a practical option. |
Since .Net 5 there is a solution to the problem that this issue tries to solve using Optional<T> and a Custom Converter. See https://stackoverflow.com/questions/63418549/custom-json-serializer-for-optional-property-with-system-text-json and https://stackoverflow.com/questions/71024060/distinguish-between-null-and-not-present-using-json-merge-patch-with-netcore-web/71074603#71074603 It took me a few weeks to find this solution and effort to adopt it when enable and nullable is set. Two steps from the .Net team would make it easy to handle this common requirement:
optional: Add a JsonIgnoreCondition 'WhenOptionalIsUndefined' or 'WhenOptionalHasNoValue' |
My proposal hasn't received any feedback. Is this feature already planned for version 7? |
Per my comment in #40395 (comment), we believe that the feature can be implemented using customized contract resolvers (under proposal #63686). We have listed this particular issue as part of the acceptance criteria. |
Thanks for your answer. Since Optionals<T?> are required for any serious project with access permissions or PATCH Merge commands Optionals<T?> should be supported out of the box, without having to write any customized contract resolver. |
The release of the contract customization feature in .NET 7 Preview 6 should make it possible to add support for the Lines 728 to 774 in 1958812
|
Per my earlier comment, adding support for the "Specified" convention should be achievable via contract customization starting in .NET 7. We're not planning on adding out-of-the-box support for this, but it should still be possible for third-party extension libraries to ship contract resolvers offering this functionality. |
Background and Motivation
Both the XmlSerializer and @JamesNK 's JSON.Net support the convention that whether a property on a class (say property XYZ) should be serialized or has been deserialized can be controlled/reported through a second property on the class (which is named by convention as XYZSpecified).
See
runtime/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs
Line 606 in 6072e4d
https://github.com/JamesNK/Newtonsoft.Json/blob/6b9f467e817854532ea31e6c08abe47c53ac8b5c/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs#L533
https://github.com/JamesNK/Newtonsoft.Json/blob/7217c484e9705b5e76585c8b7fcd489c8e021c23/Src/Newtonsoft.Json.Tests/Serialization/ShouldSerializeTests.cs#L217
This allows any code working with the deserialized data to tell the difference between a property that has a default value because the source document didn't have a value, and a document that did have a value but it happened to equal the default value. It also allows any code working with the serializer to optionally decide whether a particular property should be serialized or not (at run time).
This is extremely useful when trying to make an API backwards compatible. Say you add a property "NumberOfChildren" to a"Person" class. New client applications will send in values for how many children the person has, but old client applications won't. However, if your code cannot tell the difference between a new client application setting the property to zero and an old client just not sending the data at all, you could mistakenly overwrite the NumberOfChildren value stored in your database.
Proposed API
Please have System.Text.Json allow the calling code to optionally (at runtime) decide whether a particular property should be serialized or not on an object by object basis. Also allow the calling code to be able to tell if a property's value is set because it was deserialised or because it is the default value for the property.
Usage Examples
During serialization:
During deserialization:
Alternative Designs
Maybe tere is already a way to achieve this that I have missed.
Risks
Performance overhead of looking for "Specified" properties. Also, most "Specified" properties need to be ignored either by using the JsonIgnore or a convention to ignore them.
The text was updated successfully, but these errors were encountered: