Required properties

Starting in .NET 7, you can mark certain properties to signify that they must be present in the JSON payload for deserialization to succeed. If one or more of these required properties is not present, the JsonSerializer.Deserialize methods throw a JsonException.

There are three ways to mark a property or field as required for JSON deserialization:

From the serializer's perspective, these two demarcations are equivalent and both map to the same piece of metadata, which is JsonPropertyInfo.IsRequired. In most cases, you'd simply use the built-in C# keyword. However, in the following cases, you should use JsonRequiredAttribute instead:

  • If you're using a programming language other than C# or a down-level version of C#.
  • If you only want the requirement to apply to JSON deserialization.
  • If you're using System.Text.Json serialization in source generation mode. In this case, your code won't compile if you use the required modifier, as source generation occurs at compile time.

The following code snippet shows an example of a property modified with the required keyword. This property must be present in the JSON payload for deserialization to succeed.

using System.Text.Json;

// The following line throws a JsonException at run time.
Console.WriteLine(JsonSerializer.Deserialize<Person>("""{"Age": 42}"""));

public class Person
{
    public required string Name { get; set; }
    public int Age { get; set; }
}

Alternatively, you can use JsonRequiredAttribute:

using System.Text.Json;

// The following line throws a JsonException at run time.
Console.WriteLine(JsonSerializer.Deserialize<Person>("""{"Age": 42}"""));

public class Person
{
    [JsonRequired]
    public string Name { get; set; }
    public int Age { get; set; }
}

It's also possible to control whether a property is required via the contract model using the JsonPropertyInfo.IsRequired property:

var options = new JsonSerializerOptions
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers =
        {
            static typeInfo =>
            {
                if (typeInfo.Kind != JsonTypeInfoKind.Object)
                    return;

                foreach (JsonPropertyInfo propertyInfo in typeInfo.Properties)
                {
                    // Strip IsRequired constraint from every property.
                    propertyInfo.IsRequired = false;
                }
            }
        }
    }
};

// Deserialization now succeeds even though the Name property isn't in the JSON payload.
JsonSerializer.Deserialize<Person>("""{"Age": 42}""", options);