Search code examples
c#.netjson.netdeserializationjson-deserialization

Deserialize JSON only if it specifies a value for a value type property


If I have a DTO class containing value type properties, how can I idiomatically use Newtonsoft to deserialize JSON to my DTO class while ensuring that the JSON defines the value type, possibly containing the default value for the type? So far the methods I have seen rely on checking if the value is the default value, however, this is not a suitable solution when the default value is also a valid value for the property.

Example

public class MyDto
{
    public bool MyProp { get; set; }
}
JSON Can deserialize to MyDto
{"MyProp": true} true
{"MyProp": false} true
{} false

Current solution

Currently I use System.ComponentModel.DataAnnotations.RequiredAttribute and declare the type as nullable, but this only works during model binding (instead of any deserialization), and leads to excessive use of ! when referencing the property.

public class MyDto
{
    [Required]
    public bool? MyProp { get; set; }
}

Solution

  • I believe what you're looking for is the JsonPropertyAttribute Required property:

    public class MyDto
    {
        [JsonProperty(Required = Required.Always)]
        public bool MyProp { get; set; }
    }
    

    This results in an exception when the JSON being deserialized does not contain the specified property (MyProp). For example, the following:

    string json = "{\"MyProp\": true}";
    MyDto myDto = JsonConvert.DeserializeObject<MyDto>(json);
    Console.WriteLine(myDto.MyProp);
    
    json = "{\"MyProp\": false}";
    myDto = JsonConvert.DeserializeObject<MyDto>(json);
    Console.WriteLine(myDto.MyProp);
    
    json = "{}";
    myDto = JsonConvert.DeserializeObject<MyDto>(json);
    Console.WriteLine(myDto.MyProp);
    

    Gives the result:

    True
    False
    Run-time exception (line 17): Required property 'MyProp' not found in JSON. Path '', line 1, position 2.