Обязательные свойства

Начиная с .NET 7, можно пометить определенные свойства, чтобы означать, что они должны присутствовать в полезных данных JSON для успешной десериализации. Если один или несколько из этих обязательных свойств отсутствуют, JsonSerializer.Deserialize методы вызывают JsonExceptionисключение.

Для десериализации JSON можно пометить свойство или поле тремя способами:

С точки зрения сериализатора эти два демарации эквивалентны и оба сопоставляются с одной и той же частью метаданных, то есть JsonPropertyInfo.IsRequired. В большинстве случаев вы просто используете встроенные ключевое слово C#. Однако в следующих случаях следует использовать JsonRequiredAttribute следующее:

  • Если вы используете язык программирования, отличный от C# или версию C#нижнего уровня.
  • Если требуется применить только требование к десериализации JSON.
  • При использовании System.Text.Json сериализации в режиме создания источника. В этом случае код не будет компилироваться, если используется required модификатор, так как создание источника происходит во время компиляции.

В следующем фрагменте кода показан пример свойства, измененного с помощью required ключевое слово. Это свойство должно присутствовать в полезных данных JSON для успешной десериализации.

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; }
}

В качестве альтернативы вы можете использовать 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; }
}

Кроме того, можно контролировать, требуется ли свойство с помощью модели контракта с помощью JsonPropertyInfo.IsRequired свойства:

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);