serialization 동작 사용자 지정

완료됨

JsonSerializer.Serialize 메서드는 C# 개체를 JSON(JavaScript Object Notation) 문자열로 변환하는 데 사용됩니다. 직렬화는 다른 시스템에서 쉽게 읽고 처리할 수 있는 간단한 형식으로 데이터를 저장하거나 전송하려는 경우에 사용됩니다. 클래스는 JsonSerializer C#에서 System.Text.Json JSON 데이터 작업을 위한 기능을 제공하는 네임스페이스의 일부입니다.

다음 코드에서는 다음을 사용하여 JsonSerializer.Serialize개체를 JSON 문자열로 변환하는 방법을 보여 줍니다.


var customer = new Employee { Name = "Anette Thomsen", Age = 30, Address = "123 Main St" };
string jsonString = JsonSerializer.Serialize(customer);

기본 serialization 동작

JSON을 serialize할 때 적용되는 기본 동작은 다음과 같습니다.

  • 기본적으로 모든 public 속성은 직렬화됩니다. 무시할 속성을 지정할 수 있습니다. 프라이빗 멤버를 포함할 수도 있습니다.
  • 기본 인코더는 비 ASCII 문자, ASCII 범위 내의 HTML 구분 문자 및 RFC 8259 JSON 사양에 따라 이스케이프해야 하는 문자를 이스케이프합니다.
  • 기본적으로 JSON은 축소됩니다. JSON을 인쇄할 수 있습니다.
  • 기본적으로 JSON 이름의 대/소문자는 .NET 이름과 일치합니다. JSON 이름 대/소문자 구분을 사용자 지정할 수 있습니다.
  • 기본적으로 순환 참조가 검색되고 예외가 throw됩니다. 참조를 유지하고 순환 참조를 처리할 수 있습니다.
  • 기본적으로 필드는 무시됩니다. 필드를 포함할 수 있습니다.

클래스는 JsonSerializer 속성을 무시하고, 필드를 포함하고, JSON 출력의 서식을 제어하는 기능을 포함하여 serialization 동작을 사용자 지정하는 다양한 옵션과 구성을 제공합니다.

JsonSerializerOptions를 사용하여 serialization 동작 사용자 지정

클래스 JsonSerializerOptions 를 사용하면 메서드의 JsonSerializer.Serialize serialization 동작을 사용자 지정할 수 있습니다. 예를 들어 null 값을 무시하고, 필드를 포함하고, JSON 출력의 서식을 제어할지 여부와 같은 옵션을 지정할 수 있습니다.

이 단원에서는 다음 속성이 설명되어 있습니다.

  • DefaultIgnoreCondition: 이 속성은 serialization 중에 기본값이 있는 속성이 무시되는 조건을 지정합니다. 기본값이 있는 속성을 제외하여 직렬화된 JSON의 크기를 줄일 수 있습니다.
  • WriteIndented: 이 속성을 사용하면 JSON 출력을 꽤 인쇄할 수 있으므로 들여쓰기 및 줄 바꿈을 추가하여 사람이 읽을 수 있습니다.
  • IncludeFields: 이 속성은 필드를 serialization 프로세스에 포함할지 여부를 지정합니다. 기본적으로 속성만 직렬화됩니다.

일반적으로 사용되는 다른 속성은 다음과 같습니다.

  • PropertyNameCaseInsensitive: 이 속성을 사용하면 역직렬화하는 동안 속성 이름을 대/소문자를 구분하지 않습니다. JSON 데이터에 클래스 정의와 다른 대/소문자를 가진 속성 이름이 있는 경우에 유용할 수 있습니다.
  • AllowTrailingCommas: 이 속성은 JSON 배열 및 개체에서 후행 쉼표가 허용되므로 후행 쉼표가 있을 수 있는 JSON 데이터를 처리할 때 유용할 수 있습니다.
  • IgnoreNullValues: 이 속성은 serialization 중에 null 값을 무시할지 여부를 지정합니다. null 값이 있는 속성을 제외하면 직렬화된 JSON의 크기를 줄일 수 있습니다.
  • 인코더: 이 속성을 사용하면 JSON 문자열의 문자를 이스케이프하기 위한 사용자 지정 인코더를 지정할 수 있습니다. 속성 이름 또는 값에서 특수 문자를 처리할 때 유용할 수 있습니다.

serialization 중에 속성 무시

클래스는 JsonSerializer serialization 중에 속성을 무시하는 옵션을 제공합니다. 이는 JSON 출력에서 특정 속성(예: serialization과 관련이 없는 중요한 정보 또는 속성)을 제외하려는 경우에 유용합니다.

다음 조건에 따라 속성을 무시할 수 있습니다.

  • 개별 속성
  • 모든 읽기 전용 속성
  • 모든 null-value 속성
  • 모든 기본값 속성

개별 속성 무시

개별 속성을 무시하려면 [JsonIgnore] 특성을 사용합니다.

다음 예제에서는 serialize할 형식을 보여줍니다. 또한 JSON 출력도 표시합니다.


public class WeatherForecastWithIgnoreAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    [JsonIgnore]
    public string? Summary { get; set; }
}

class Program
{
    static void Main()
    {
        var forecast = new WeatherForecastWithIgnoreAttribute
        {
            Date = DateTimeOffset.Now,
            TemperatureCelsius = 25,
            Summary = "Warm"
        };

        string jsonString = JsonSerializer.Serialize(forecast);
        Console.WriteLine(jsonString);
    }
}

// Output: {"Date":"2023-10-01T12:00:00Z","TemperatureCelsius":25}

특성의 [JsonIgnore] 속성을 설정하여 조건부 제외를 Condition 지정할 수 있습니다. 열거형은 JsonIgnoreCondition 다음 옵션을 제공합니다.

  • Always - 속성은 항상 무시됩니다. 조건을 지정하지 않으면 이 옵션을 가정합니다.
  • Never - DefaultIgnoreCondition, IgnoreReadOnlyProperties 및 IgnoreReadOnlyFields 전역 설정에 관계없이 속성은 항상 직렬화되고 역직렬화됩니다.
  • WhenWritingDefault - 속성이 참조 형식 null, null 허용 값 형식 null 또는 값 형식 기본값인 경우 serialization에서 무시됩니다.
  • WhenWritingNull - 속성이 참조 형식 null이거나 nullable 값 형식인 경우 serialization에서 무시됩니다.

다음 예제에서는 [JsonIgnore] 특성의 Condition 속성을 사용하는 방법을 보여 줍니다.


using System.Text.Json;
using System.Text.Json.Serialization;

namespace JsonIgnoreAttributeExample
{
    public class Forecast
    {
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
        public DateTime Date { get; set; }

        [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
        public int TemperatureC { get; set; }

        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
        public string? Summary { get; set; }
    };

    public class Program
    {
        public static void Main()
        {
            Forecast forecast = new()
            {
                Date = default,
                Summary = null,
                TemperatureC = default
            };

            JsonSerializerOptions options = new()
            {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
            };

            string forecastJson =
                JsonSerializer.Serialize<Forecast>(forecast,options);

            Console.WriteLine(forecastJson);
        }
    }
}

// Produces output like the following example:
//
//{"TemperatureC":0}

모든 읽기 전용 속성 무시

공용 getter가 포함되지만 공용 setter가 없는 경우 속성은 읽기 전용입니다. serialize할 때 모든 읽기 전용 속성을 무시하려면 다음 예제와 같이 다음으로 설정합니다 JsonSerializerOptions.IgnoreReadOnlyPropertiestrue.


var options = new JsonSerializerOptions
{
    IgnoreReadOnlyProperties = true,
    WriteIndented = true
};

jsonString = JsonSerializer.Serialize(weatherForecast, options);

다음 예제에서는 serialize할 형식을 보여줍니다. 또한 JSON 출력도 표시합니다.


public class WeatherForecastWithROProperty
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    public int WindSpeedReadOnly { get; private set; } = 35;
}

// {
//   "Date": "2019-08-01T00:00:00-07:00",
//   "TemperatureCelsius": 25,
//   "Summary": "Hot",
// }

비고

이 옵션은 속성에만 적용됩니다. 필드를 serialize할 때 읽기 전용 필드를 무시하려면 전역 설정을 사용합니다 JsonSerializerOptions.IgnoreReadOnlyFields .

모든 null-value 속성 무시

모든 null 값 속성을 무시하려면 다음 예제와 같이 속성을 DefaultIgnoreCondition로 설정합니다WhenWritingNull.


using System.Text.Json;
using System.Text.Json.Serialization;

namespace IgnoreNullOnSerialize
{
    public class Forecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string? Summary { get; set; }
    };

    public class Program
    {
        public static void Main()
        {
            Forecast forecast = new()
            {
                Date = DateTime.Now,
                Summary = null,
                TemperatureC = default
            };

            JsonSerializerOptions options = new()
            {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
            };

            string forecastJson =
                JsonSerializer.Serialize<Forecast>(forecast, options);
            
            Console.WriteLine(forecastJson);
        }
    }
}

// Produces output like the following example:
//
//{"Date":"2020-10-30T10:11:40.2359135-07:00","TemperatureC":0}

모든 기본값 속성 무시

값 형식 속성에서 기본값이 serialization되지 않도록 하려면 다음 예제와 같이 속성을 DefaultIgnoreCondition다음으로 설정합니다WhenWritingDefault.


using System.Text.Json;
using System.Text.Json.Serialization;

namespace IgnoreValueDefaultOnSerialize
{
    public class Forecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string? Summary { get; set; }
    };

    public class Program
    {
        public static void Main()
        {
            Forecast forecast = new()
            {
                Date = DateTime.Now,
                Summary = null,
                TemperatureC = default
            };

            JsonSerializerOptions options = new()
            {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
            };

            string forecastJson =
                JsonSerializer.Serialize<Forecast>(forecast, options);

            Console.WriteLine(forecastJson);
        }
    }
}

// Produces output like the following example:
//
//{ "Date":"2020-10-21T15:40:06.8920138-07:00"}

또한 이 설정은 WhenWritingDefault null-value 참조 형식 및 nullable 값 형식 속성의 serialization을 방지합니다.

serialization 중에 필드 포함

기본적으로 속성만 직렬화되지만 필드도 포함하도록 serializer를 구성할 수 있습니다. 다음 예제와 JsonSerializerOptions.IncludeFields 같이 직렬화 또는 역직렬화할 때 필드를 포함하려면 전역 설정 또는 [JsonInclude] 특성을 사용합니다.


using System.Text.Json;
using System.Text.Json.Serialization;

namespace Fields
{
    public class Forecast
    {
        public DateTime Date;
        public int TemperatureC;
        public string? Summary;
    }

    public class Forecast2
    {
        [JsonInclude]
        public DateTime Date;
        [JsonInclude]
        public int TemperatureC;
        [JsonInclude]
        public string? Summary;
    }

    public class Program
    {
        public static void Main()
        {
            string json = """
                {
                    "Date":"2020-09-06T11:31:01.923395",
                    "TemperatureC":-1,
                    "Summary":"Cold"
                }
                """;
            Console.WriteLine($"Input JSON: {json}");

            var options = new JsonSerializerOptions
            {
                IncludeFields = true,
            };
            Forecast forecast = JsonSerializer.Deserialize<Forecast>(json, options)!;

            Console.WriteLine($"forecast.Date: {forecast.Date}");
            Console.WriteLine($"forecast.TemperatureC: {forecast.TemperatureC}");
            Console.WriteLine($"forecast.Summary: {forecast.Summary}");

            string roundTrippedJson =
                JsonSerializer.Serialize<Forecast>(forecast, options);

            Console.WriteLine($"Output JSON: {roundTrippedJson}");

            Forecast2 forecast2 = JsonSerializer.Deserialize<Forecast2>(json)!;

            Console.WriteLine($"forecast2.Date: {forecast2.Date}");
            Console.WriteLine($"forecast2.TemperatureC: {forecast2.TemperatureC}");
            Console.WriteLine($"forecast2.Summary: {forecast2.Summary}");

            roundTrippedJson = JsonSerializer.Serialize<Forecast2>(forecast2);
            
            Console.WriteLine($"Output JSON: {roundTrippedJson}");
        }
    }
}

// Produces output like the following example:
//
//Input JSON: { "Date":"2020-09-06T11:31:01.923395","TemperatureC":-1,"Summary":"Cold"}
//forecast.Date: 9/6/2020 11:31:01 AM
//forecast.TemperatureC: -1
//forecast.Summary: Cold
//Output JSON: { "Date":"2020-09-06T11:31:01.923395","TemperatureC":-1,"Summary":"Cold"}
//forecast2.Date: 9/6/2020 11:31:01 AM
//forecast2.TemperatureC: -1
//forecast2.Summary: Cold
//Output JSON: { "Date":"2020-09-06T11:31:01.923395","TemperatureC":-1,"Summary":"Cold"}

읽기 전용 필드를 무시하려면 JsonSerializerOptions.IgnoreReadOnlyFields 전역 설정을 사용합니다.

JSON 파일 작성

JSON 데이터를 사용하는 경우 JSON 파일 작성은 일반적인 작업입니다. 이 클래스는 JsonSerializer 개체를 JSON 문자열로 직렬화하는 메서드를 제공하므로 파일에 저장할 수 있습니다. 이 메서드를 File.WriteAllText 사용하여 JSON 문자열을 파일에 쓸 수 있습니다.

다음 예제에서는 개체를 JSON으로 직렬화하고 파일에 저장하는 방법을 보여 줍니다.


using System;
using System.IO;
using System.Text.Json;

class Program
{
      static void Main()
      {
          var customer = new BankCustomer {  };
          string jsonString = JsonSerializer.Serialize(customer);
          File.WriteAllText("customer.json", jsonString);
          Console.WriteLine("JSON file created and saved.");
      }
}

요약

이 단원에서는 메서드를 사용하여 JsonSerializer.Serialize C# 개체를 serialize할 때 serialization 동작을 사용자 지정하는 방법을 알아보았습니다. serialization 중에 속성 및 필드를 무시하는 방법과 파일에 JSON 데이터를 쓰는 방법을 알아보았습니다. 이 지식은 C# 애플리케이션에서 JSON 데이터를 사용하는 데 필수적입니다.