This question already has answers here:
Closed 4 years ago.
Using Json.net deserialization is there a way I can distinguish between null value and value that isn't provided i.e. missing key?
I'm considering this for partial object updates using PATCH requests and they would represent different intents:
- Null -> set this property to null
- Missing -> skip properties not provided
In javascript this is the difference between undefined and null.
The best I came up with for now is to use JObject
.
I had the exact same issue and I stumbled on this question during my researches.
Unsatisfied by the general consensus, I created an extended Nullable struct, which I called Settable<T> for lack of imagination. Basically it is a nullable with an additional field, IsSet, which is true no matter which value you stored, as long as you stored something, and false only for default(Settable<T>), which is aliased as Settable<T>.Undefined.
A deserializer is going to write the Settable<T> only if he finds a corresponding property, in which case IsSet will be true. If the property is not included in the deserialized json, the default will be retained, which has IsSet == false. So, replacing your int? properties in your DTO type with a Settable is going to give you the required difference between undefined (or, more exactly, unspecified) and null.
Yay!
I uploaded the implementation into a repository on Github, for everyone to use (no warranty, use at your own risk, etc... I'm in hospital with 6 broken ribs and under painkillers: if something doesn't work it's YOUR fault):
https://github.com/alberto-chiesa/SettableJsonProperties
Edit:
As for the comment about undefined serializing to null, I added a custom ContractResolver to handle Settable properties and updated the repository.
The answer here seems to be what you are after: https://stackoverflow.com/a/21820736/39532
The basic summary is:
- undefined isn't directly supported by JSON since not setting a
property is functionally equivalent
- Null may be represented by
new JValue((object)null)