Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json.NET require all properties on deserialization

Tags:

In Json.NET, how do I make ALL properties required upon deserialization? I know that I can do this with attributes on the messages, but I don't want to do that. Mainly because it would require my message library to take on an external dependency.

I tried the MissingMemberHandling.Error setting, but it does the opposite of what I want. I'm okay with the JSON having extra properties. I want it to fail when any target object properties are missing in the JSON.

I'm actually deserializing to F# records, and the properties can't ordinarily be null anyway. (They can't be assigned null by normal means in code.) But Json.NET happily defaults properties to null under the covers when data is missing.


F# version of accepted answer

Resolver

open System open Newtonsoft.Json open Newtonsoft.Json.Serialization  type RequireAllPropertiesContractResolver() =     inherit DefaultContractResolver()      override me.CreateObjectContract(objectType:Type) =         let contract = base.CreateObjectContract(objectType)         contract.ItemRequired <- new Nullable<Required>(Required.Always)         contract 

In the settings

let settings = new JsonSerializerSettings() // default settings ... settings.ContractResolver <- new RequireAllPropertiesContractResolver() 
like image 562
Kasey Speakman Avatar asked Apr 15 '15 16:04

Kasey Speakman


People also ask

How does JSON deserialization work?

In Deserialization, it does the opposite of Serialization which means it converts JSON string to custom . Net object. In the following code, it calls the static method DeserializeObject() of the JsonConvert class by passing JSON data. It returns a custom object (BlogSites) from JSON data.

Which of the following attributes are required to ignore properties for JSON serializer?

To ignore individual properties, use the [JsonIgnore] attribute.

What does Jsonproperty attribute do?

JsonPropertyAttribute indicates that a property should be serialized when member serialization is set to opt-in. It includes non-public properties in serialization and deserialization. It can be used to customize type name, reference, null, and default value handling for the property value.

Why do we need serialization and deserialization in JSON?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object). If you serialize this result it will generate a text with the structure and the record returned.


1 Answers

If your model has properties that your JSON may omit, and you want that to be an error, add the attribute [JsonObject(ItemRequired=Required.Always)] to your classes:

Type: Required

A value indicating whether the object's properties are required.

Possible values for Required are:

  • Default: The property is not required. The default state.
  • AllowNull: The property must be defined in JSON but can be a null value.
  • Always: The property must be defined in JSON and cannot be a null value.
  • DisallowNull: The property is not required but it cannot be a null value [if present]. (Json.NET 8.0.1 and later.)

The setting is inherited so can be added to a generic base class.

Update

To do it globally for all objects, subclass the DefaultContractResolver and add the ItemRequired flag to all object contracts:

public class RequireObjectPropertiesContractResolver : DefaultContractResolver {     protected override JsonObjectContract CreateObjectContract(Type objectType)     {         var contract = base.CreateObjectContract(objectType);         contract.ItemRequired = Required.Always;         return contract;     } } 

And then later, in settings:

var settings = new JsonSerializerSettings { ContractResolver = new RequireObjectPropertiesContractResolver() }; 

Notes:

  • If you don't want to require JSON properties when your f# member is optional see this answer to this question and also the question Json.NET make property required based on property type.

  • This contract resolver applies a default setting of Required.Always to all object properties, but will not override JsonProperty.AttributeRequired when applied directly. If you need that, see e.g. How to override the "Required.Always" in newtonsoft json.

  • As stated in the question, the setting MissingMemberHandling = MissingMemberHandling.Error solves a complimentary problem: if your JSON may have properties that your model omits, and you want that to be an error, use MissingMemberHandling.Error. See: MissingMemberHandling setting.

  • You may want to cache the contract resolver for best performance.

like image 135
dbc Avatar answered Sep 27 '22 17:09

dbc