다음을 통해 공유


nullable 주석 존중

.NET 9 JsonSerializer 부터 직렬화 및 역직렬화 모두에서 nullable이 아닌 참조 형식 적용을 지원합니다(제한). 플래그를 사용하여 이 지원을 전환할 JsonSerializerOptions.RespectNullableAnnotations 수 있습니다.

예를 들어 다음 코드 조각은 직렬화 중에 다음과 같은 메시지와 함께 throw합니다 JsonException .

'Person' 형식의 속성 또는 필드 'Name'은 null 값을 가져올 수 없습니다. Null 허용 여부 주석을 업데이트하는 것이 좋습니다.

    public static void RunIt()
    {
#nullable enable
        JsonSerializerOptions options = new()
        {
            RespectNullableAnnotations = true
        };

        Person invalidValue = new(Name: null!);
        JsonSerializer.Serialize(invalidValue, options);
    }

    record Person(string Name);

마찬가지로 역 RespectNullableAnnotations 직렬화에 대해 null 허용을 적용합니다. 다음 코드 조각은 직렬화 중에 다음과 같은 메시지와 함께 throw합니다 JsonException .

'Person' 형식의 생성자 매개 변수 'Name'은 null 값을 허용하지 않습니다. Null 허용 여부 주석을 업데이트하는 것이 좋습니다.

    public static void RunIt()
    {
#nullable enable
        JsonSerializerOptions options = new()
        {
            RespectNullableAnnotations = true
        };

        string json = """{"Name":null}""";
        JsonSerializer.Deserialize<Person>(json, options);
    }

    record Person(string Name);

제한 사항

nullable이 아닌 참조 형식을 구현하는 방법 때문에 이 기능에는 몇 가지 중요한 제한 사항이 있습니다. 기능을 켜기 전에 이러한 제한 사항을 숙지하세요. 문제의 근본 원인은 참조 형식 nullability에 IL(중간 언어)의 첫 번째 클래스 표현이 없다는 것입니다. 따라서 식 MyPocoMyPoco? 런타임 리플렉션의 관점에서 구별할 수 없습니다. 컴파일러가 특성 메타데이터를 내보내서 이를 만회하려고 하는 동안(예제 sharplab.io 참조), 이 메타데이터는 특정 형식 정의로 범위가 지정된 제네릭이 아닌 멤버 주석으로 제한됩니다. 이 제한 사항은 플래그가 제네릭이 아닌 속성, 필드 및 생성자 매개 변수에 있는 null 허용 여부 주석만 유효성을 검사하는 이유입니다. System.Text.Json 에서는 다음에서 Null 허용 여부 적용을 지원하지 않습니다.

  • 최상위 형식 또는 첫 번째 JsonSerializer.Deserialize() 또는 JsonSerializer.Serialize() 호출을 할 때 전달되는 형식입니다.
  • 컬렉션 요소 형식(예: List<string> 형식 및 List<string?> 형식은 구별할 수 없음)입니다.
  • 제네릭인 모든 속성, 필드 또는 생성자 매개 변수입니다.

이러한 경우 null 허용 여부 적용을 추가하려면 형식을 구조체로 모델링하거나(null 값을 인정하지 않으므로) 해당 HandleNull 속성을 true재정의하는 사용자 지정 변환기를 작성합니다.

기능 전환

기능 스위치를 RespectNullableAnnotations 사용하여 System.Text.Json.Serialization.RespectNullableAnnotationsDefault 전역적으로 설정을 켤 수 있습니다. 프로젝트 파일(예 : .csproj 파일)에 다음 MSBuild 항목을 추가합니다.

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
</ItemGroup>

API는 RespectNullableAnnotationsDefault 기존 애플리케이션을 중단하지 않도록 .NET 9에서 옵트인 플래그로 구현되었습니다. 새 애플리케이션을 작성하는 경우 코드에서 이 플래그를 사용하도록 설정하는 것이 좋습니다.

nullable 매개 변수와 선택적 매개 변수 간의 관계

RespectNullableAnnotations 는 필수 및 nullable이 아닌 속성을 직교 개념으로 처리하므로 적용을 지정되지 않은 JSON 값 System.Text.Json 으로 확장하지 않습니다. 예를 들어 다음 코드 조각은 역직렬화 중에 예외를 throw하지 않습니다.

public static void RunIt()
{
    JsonSerializerOptions options = new()
    {
        RespectNullableAnnotations = true
    };
    var result = JsonSerializer.Deserialize<MyPoco>("{}", options);
    Console.WriteLine(result.Name is null); // True.
}

class MyPoco
{
    public string Name { get; set; }
}

이 동작은 Null 허용 필수 속성을 가질 수 있는 C# 언어 자체에서 비롯됩니다.

MyPoco poco = new() { Value = null }; // No compiler warnings.

class MyPoco
{
    public required string? Value { get; set; }
}

또한 null을 허용하지 않는 선택적 속성을 가질 수도 있습니다.

class MyPoco
{
    public string Value { get; set; } = "default";
}

생성자 매개 변수에 동일한 직교가 적용됩니다.

record MyPoco(
    string RequiredNonNullable,
    string? RequiredNullable,
    string OptionalNonNullable = "default",
    string? OptionalNullable = "default"
    );

참고 항목