System.Text.Json에서 Utf8JsonWriter를 사용하는 방법

이 문서에서는 사용자 지정 직렬 변환기를 빌드하는 데 Utf8JsonWriter 형식을 사용하는 방법을 보여 줍니다.

Utf8JsonWriterString, Int32DateTime과 같은 일반적인 .NET 형식에서 UTF-8 인코딩 JSON 텍스트를 쓸 수 있는 고성능 방법을 제공합니다. writer는 사용자 지정 직렬 변환기를 빌드하는 데 사용할 수 있는 하위 수준 형식입니다. JsonSerializer.Serialize 메서드는 내부적으로 Utf8JsonWriter를 사용합니다.

다음 예제에서는 Utf8JsonWriter 클래스 사용 방법을 보여줍니다.

var options = new JsonWriterOptions
{
    Indented = true
};

using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, options);

writer.WriteStartObject();
writer.WriteString("date", DateTimeOffset.UtcNow);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
writer.Flush();

string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
Dim options As JsonWriterOptions = New JsonWriterOptions With {
    .Indented = True
}

Dim stream As MemoryStream = New MemoryStream
Dim writer As Utf8JsonWriter = New Utf8JsonWriter(stream, options)

writer.WriteStartObject()
writer.WriteString("date", DateTimeOffset.UtcNow)
writer.WriteNumber("temp", 42)
writer.WriteEndObject()
writer.Flush()

Dim json As String = Encoding.UTF8.GetString(stream.ToArray())
Console.WriteLine(json)

UTF-8 텍스트를 사용하여 쓰기

Utf8JsonWriter를 사용할 때 가능한 최상의 성능을 얻으려면 UTF-16 문자열이 아닌 UTF-8 텍스트로 이미 인코드된 JSON 페이로드를 쓰세요. UTF-16 문자열 리터럴을 사용하는 대신 JsonEncodedText를 사용하여 알려진 문자열 속성 이름 및 값을 정적으로 캐시 및 미리 인코딩하여 작성기에 전달하세요. 이 방법이 UTF-8 바이트 배열을 캐시하여 사용하는 것보다 빠릅니다.

이 방법은 사용자 지정 이스케이프를 수행해야 하는 경우에도 통합니다. System.Text.Json은 문자열을 작성하는 동안 이스케이프를 해제할 수 없습니다. 그러나 사용자 지정 JavaScriptEncoder를 작성기에 옵션으로 전달하거나, 자체 JavascriptEncoder를 사용하여 이스케이프를 수행하는 고유한 JsonEncodedText를 만든 후 문자열 대신 JsonEncodedText를 작성할 수 있습니다. 자세한 내용은 문자 인코딩 사용자 지정을 참조하세요.

원시 JSON 작성

일부 시나리오에서는 Utf8JsonWriter를 사용하여 만드는 JSON 페이로드에 ‘원시’ JSON을 작성할 수 있습니다. Utf8JsonWriter.WriteRawValue를 사용하여 이 작업을 수행할 수 있습니다. 일반적인 시나리오는 다음과 같습니다.

  • 새 JSON에 묶을 기존 JSON 페이로드가 있습니다.

  • 값의 서식을 기본 Utf8JsonWriter 서식과 다르게 지정하려고 합니다.

    예를 들어, 숫자 서식을 필요에 따라 사용자 지정할 수 있습니다. 기본적으로 System.Text.Json은 정수에 대한 소수점을 생략합니다. 예를 들어 1.0이 아닌 1을 작성합니다. 그 이유는 더 적은 바이트를 쓰는 것이 성능에 좋다는 것입니다. 그러나 JSON의 소비자가 10진수가 있는 숫자를 double로 처리하고 소수점이 없는 숫자를 정수로 처리한다고 가정해 보겠습니다. 정수에 대해 소수점과 0을 작성하여 배열의 숫자가 모두 double로 인식되도록 할 수 있습니다. 다음 예제에서는 해당 작업을 수행하는 방법을 보여줍니다.

    using System.Text;
    using System.Text.Json;
    
    namespace WriteRawJson;
    
    public class Program
    {
        public static void Main()
        {
            JsonWriterOptions writerOptions = new() { Indented = true, };
    
            using MemoryStream stream = new();
            using Utf8JsonWriter writer = new(stream, writerOptions);
    
            writer.WriteStartObject();
    
            writer.WriteStartArray("defaultJsonFormatting");
            foreach (double number in new double[] { 50.4, 51 })
            {
                writer.WriteStartObject();
                writer.WritePropertyName("value");
                writer.WriteNumberValue(number);
                writer.WriteEndObject();
            }
            writer.WriteEndArray();
    
            writer.WriteStartArray("customJsonFormatting");
            foreach (double result in new double[] { 50.4, 51 })
            {
                writer.WriteStartObject();
                writer.WritePropertyName("value");
                writer.WriteRawValue(
                    FormatNumberValue(result), skipInputValidation: true);
                writer.WriteEndObject();
            }
            writer.WriteEndArray();
    
            writer.WriteEndObject();
            writer.Flush();
    
            string json = Encoding.UTF8.GetString(stream.ToArray());
            Console.WriteLine(json);
        }
        static string FormatNumberValue(double numberValue)
        {
            return numberValue == Convert.ToInt32(numberValue) ? 
                numberValue.ToString() + ".0" : numberValue.ToString();
        }
    }
    // output:
    //{
    //  "defaultJsonFormatting": [
    //    {
    //      "value": 50.4
    //    },
    //    {
    //      "value": 51
    //    }
    //  ],
    //  "customJsonFormatting": [
    //    {
    //      "value": 50.4
    //    },
    //    {
    //      "value": 51.0
    //    }
    //  ]
    //}
    

문자 이스케이프 사용자 지정

JsonTextWriterStringEscapeHandling 설정은 모든 비 ASCII 문자 또는 HTML 문자를 이스케이프하는 옵션을 제공합니다. 기본적으로 Utf8JsonWriter는 모든 비 ASCII 문자 HTML 문자를 이스케이프합니다. 이러한 이스케이프는 심층 방어 보안을 위해 수행됩니다. 다른 이스케이프 정책을 지정하려면 JavaScriptEncoder를 만들고 JsonWriterOptions.Encoder을 설정하세요. 자세한 내용은 문자 인코딩 사용자 지정을 참조하세요.

null 값 쓰기

Utf8JsonWriter를 사용하여 null 값을 쓰려면 다음을 호출합니다.

  • WriteNull - Null을 사용하는 키-값 쌍을 값으로 씁니다.
  • WriteNullValue - Null을 JSON 배열의 요소로 씁니다.

문자열 속성의 경우 문자열이 Null이면 WriteStringWriteStringValueWriteNullWriteNullValue와 동일합니다.

Timespan, Uri 또는 char 값 쓰기

Timespan, Uri 또는 char 값을 작성하려면 (예를 들어 ToString()을 호출하여) 문자열로 그 값의 서식을 지정하고 WriteStringValue를 호출합니다.

참고 항목