How to distinguish between null value and value no

2020-03-02 03:45发布

问题:

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.

回答1:

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.



回答2:

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)