Newtonsoft.Json에서 System.Text.Json(으)로 마이그레이션
이 문서에서는 Newtonsoft.Json에서 System.Text.Json로 마이그레이션하는 방법을 보여줍니다.
System.Text.Json
네임스페이스는 JSON(JavaScript Object Notation)에서 직렬화 및 역직렬화하는 기능을 제공합니다. System.Text.Json
라이브러리는 .NET Core 3.1 이상 버전의 런타임에 포함되어 있습니다. 다른 대상 프레임워크의 경우 System.Text.Json NuGet 패키지를 설치합니다. 패키지는 다음을 지원합니다.
- .NET Standard 2.0 이상 버전
- .NET Framework 4.6.2 이전 버전
- .NET Core 2.0, 2.1, 2.2
팁
AI 지원을 사용하여 GitHub Copilot을 통해 Newtonsoft.Json
에서 마이그레이션할 수 있습니다.
System.Text.Json
은 성능, 보안 및 표준 규정 준수에 중점을 둡니다. 기본 동작에서 몇 가지 큰 차이가 있으며 Newtonsoft.Json
과의 기능 패리티를 목표로 하지 않습니다. 일부 시나리오에서는 현재 System.Text.Json
에 기본 제공 기능이 없지만, 권장 해결 방법이 있습니다. 그 외의 시나리오에서는 해결 방법이 실용적이지 않습니다.
System.Text.Json
팀은 가장 자주 요청된 기능을 추가하는 데 투자하고 있습니다. 애플리케이션에서 사용하는 기능이 없는 경우 dotnet/runtime GitHub 리포지토리에서 이슈를 제출하여 해당 시나리오에 대한 지원을 추가할 수 있는지 알아보세요.
이 문서의 대부분은 JsonSerializer API 사용 방법에 대한 내용이지만, JsonDocument(DOM(문서 개체 모델)을 나타냄), Utf8JsonReader 및 Utf8JsonWriter 형식을 사용하는 방법에 대한 지침도 포함되어 있습니다.
Visual Basic에서는 Utf8JsonReader를 사용할 수 없습니다. 즉, 사용자 지정 변환기를 작성할 수 없습니다. 여기에 제시된 대부분의 해결 방법은 사용자 지정 변환기를 작성해야 합니다. C#에서 사용자 지정 변환기를 작성하고 Visual Basic 프로젝트에 등록할 수 있습니다. 자세한 내용은 Visual Basic 지원을 참조하세요.
차이점 표
다음 표에는 Newtonsoft.Json
기능과 그에 상응하는 System.Text.Json
기능이 나열되어 있습니다. 상응하는 기능은 다음 범주로 분류됩니다.
- ✔️ 기본 제공 기능에서 지원됩니다.
System.Text.Json
에서 유사한 동작을 가져오려면 특성 또는 글로벌 옵션을 사용해야 할 수도 있습니다. - ⚠ 지원되지 않지만 해결이 가능합니다. 해결 방법은 사용자 지정 변환기이며, 사용자 지정 변환기는
Newtonsoft.Json
기능과의 완전한 패리티를 제공하지 않을 수 있습니다. 그 중 일부는 샘플 코드가 예제로 제공됩니다. 이러한Newtonsoft.Json
기능을 사용하는 경우 마이그레이션을 수행하려면 .NET 개체 모델 또는 기타 코드 변경 내용을 수정해야 합니다. - ❌ 지원되지 않으며 해결 방법이 실용적이지 않거나 가능하지 않습니다. 이러한
Newtonsoft.Json
기능을 사용하는 경우 중요한 변경 없이는 마이그레이션을 수행할 수 없습니다.
Newtonsoft.Json 기능 | System.Text.Json 해당 항목 |
---|---|
기본적으로 대/소문자를 구분하지 않는 역직렬화 | ✔️ PropertyNameCaseInsensitive 글로벌 설정 |
카멜식 대/소문자 속성 이름 | ✔️ PropertyNamingPolicy 글로벌 설정 |
스네이크 케이스 속성 이름 | ✔️ 스네이크 표기법 이름 지정 정책 |
최소 문자 이스케이프 | ✔️ 엄격한 문자 이스케이프, 구성 가능 |
NullValueHandling.Ignore 글로벌 설정 |
✔️ DefaultIgnoreCondition 전역 옵션 |
주석 허용 | ✔️ ReadCommentHandling 글로벌 설정 |
후행 쉼표 허용 | ✔️ AllowTrailingCommas 글로벌 설정 |
사용자 지정 변환기 등록 | ✔️ 우선 순위가 다름 |
기본 최대 깊이는 64, 구성 가능 | ✔️ 기본 최대 깊이는 64, 구성 가능 |
PreserveReferencesHandling 글로벌 설정 |
✔️ ReferenceHandling 전역 설정 |
따옴표 안의 숫자를 직렬화하거나 역직렬화 | ✔️ NumberHandling 전역 설정, [JsonNumberHandling] 특성 |
변경할 수 없는 클래스 및 구조체로 역직렬화 | ✔️ JsonConstructor, C# 9 레코드 |
필드에 대한 지원 | ✔️ IncludeFields 전역 설정, [JsonInclude] 특성 |
DefaultValueHandling 글로벌 설정 |
✔️ DefaultIgnoreCondition 전역 설정 |
NullValueHandling 에서의 [JsonProperty] 설정 |
✔️ JsonIgnore 특성 |
DefaultValueHandling 에서의 [JsonProperty] 설정 |
✔️ JsonIgnore 특성 |
문자열이 아닌 키로 Dictionary 역직렬화 |
✔️ 지원됨 |
public이 아닌 속성 setter 및 getter 지원 | ✔️ JsonInclude 특성 |
[JsonConstructor] 특성 |
✔️ JsonConstructor 특성 |
ReferenceLoopHandling 글로벌 설정 |
✔️ ReferenceHandling 전역 설정 |
콜백 | ✔️ 콜백 |
NaN, Infinity, -Infinity | ✔️ 지원됨 |
Required 특성에 대한 [JsonProperty] 설정 |
✔️ [JsonRequired] 특성 및 C# 필수 한정자 |
속성을 무시하는 DefaultContractResolver |
✔️ DefaultJsonTypeInfoResolver 클래스 |
다형 직렬화 | ✔️ [JsonDerivedType] 특성 |
다형 역직렬화 | ✔️ [JsonDerivedType] 특성에 대한 형식 판별자 |
문자열 열거형 값 역직렬화 | ✔️ 문자열 열거형 값 역직렬화 |
MissingMemberHandling 글로벌 설정 |
✔️ 누락된 멤버 처리 |
setter 없이 속성 채우기 | ✔️ setter 없이 속성 채우기 |
ObjectCreationHandling 글로벌 설정 |
✔️ 속성을 바꾸지 않고 재사용 |
광범위한 형식 지원 | ⚠️ 일부 형식은 사용자 지정 변환기 필요 |
유추 형식을 object 속성으로 역직렬화 |
⚠️ 지원되지 않음, 해결 가능, 샘플 |
JSON null 리터럴을 null을 허용하지 않는 값 형식으로 역직렬화 |
⚠️ 지원되지 않음, 해결 가능, 샘플 |
DateTimeZoneHandling , DateFormatString 설정 |
⚠️ 지원되지 않음, 해결 가능, 샘플 |
JsonConvert.PopulateObject 메서드 |
⚠지원되지 않음, 해결 가능 |
System.Runtime.Serialization 특성 지원 |
⚠️ 지원되지 않음, 해결 가능, 샘플 |
JsonObjectAttribute |
⚠️ 지원되지 않음, 해결 가능 |
따옴표 없는 속성 이름 허용 | ❌디자인에서 지원되지 않음 |
문자열 값 주변에 작은따옴표 허용 | ❌디자인에서 지원되지 않음 |
문자열 속성에 문자열이 아닌 JSON 값 허용 | ❌디자인에서 지원되지 않음 |
TypeNameHandling.All 글로벌 설정 |
❌디자인에서 지원되지 않음 |
JsonPath 쿼리 지원 |
❌지원되지 않음 |
구성 가능한 제한 | ❌지원되지 않음 |
이 목록은 Newtonsoft.Json
기능의 전체 목록이 아닙니다. 이 목록에는 GitHub 이슈 또는 StackOverflow 게시물에 요청된 여러 시나리오가 포함되어 있습니다. 여기에 나열된 시나리오 중에서 현재 샘플 코드가 없는 시나리오에 대한 해결 방법을 구현하셨으며 그 방법을 공유하려는 분들은 이 페이지 하단의 피드백 섹션에서 이 페이지를 선택하세요. 그러면 이 설명서의 GitHub 리포지토리에 이슈가 작성되고 이 페이지의 피드백 섹션에도 이슈가 나열됩니다.
기본 동작의 차이점
System.Text.Json은 기본적으로 엄격하며, 호출자를 대신하여 추측하거나 해석하는 것을 금지하고 결정적 동작을 강조합니다. 이 라이브러리는 성능과 보안을 위해 의도적으로 이렇게 설계되었습니다. Newtonsoft.Json
은 기본적으로 유연합니다. 이러한 기본적인 디자인의 차이로 인해 기본 동작에서 다음과 같은 여러 가지 차이가 있습니다.
대/소문자를 구분하지 않는 역직렬화
역직렬화를 수행하는 동안 Newtonsoft.Json
은 기본적으로 대/소문자를 구분하지 않는 속성 이름을 매칭합니다. System.Text.Json은 기본적으로 대/소문자를 구분하며, 이 방법은 매칭을 정확히 수행하기 때문에 보다 나은 성능을 제공합니다. 대/소문자를 구분하지 않는 매칭 방법에 대한 자세한 내용은 대/소문자를 구분하지 않는 속성 매칭을 참조하세요.
ASP.NET Core를 사용하여 간접적으로 System.Text.Json
을 사용하는 경우 Newtonsoft.Json
과 같은 동작을 얻기 위해 아무것도 할 필요가 없습니다. ASP.NET Core는 System.Text.Json
을(를) 사용할 때 카멜식 대/소문자 구분 속성 이름 및 대/소문자를 구분하지 않는 매칭에 대한 설정을 지정합니다.
ASP.NET Core에서는 기본적으로 따옴표 붙은 숫자의 역직렬화도 가능합니다.
최소 문자 이스케이프
직렬화할 때 Newtonsoft.Json
은 문자를 이스케이프하지 않고 허용하는 것에 대해 비교적 관대합니다. 즉, 문자를 \uxxxx
로 바꾸지 않으며, 여기서 xxxx
는 문자의 코드 포인트입니다. 문자를 이스케이프할 때는 문자 앞에 \
를 내보냅니다. 예를 들어 "
는 \"
가 됩니다. System.Text.Json은 XSS(교차 사이트 스크립팅) 또는 정보 공개 공격에 대한 심층 방어를 제공하기 위해 기본적으로 더 많은 문자를 이스케이프하며, 그러기 위해 6문자 시퀀스를 사용합니다. System.Text.Json
은 기본적으로 ASCII가 아닌 모든 문자를 이스케이프하므로, Newtonsoft.Json
에서 StringEscapeHandling.EscapeNonAscii
를 사용 중이라면 아무것도 할 필요가 없습니다. 또한 System.Text.Json
은 기본적으로 HTML 구분 문자를 이스케이프합니다. 기본 System.Text.Json
동작을 재정의하는 방법에 대한 자세한 내용은 문자 인코딩 사용자 지정을 참조하세요.
주석
역직렬화할 때 Newtonsoft.Json
은 기본적으로 JSON의 주석을 무시합니다. RFC 8259 사양에 주석이 포함되지 않기 때문에 System.Text.Json은 기본적으로 주석에 대해 예외를 throw합니다. 주석을 허용하는 방법에 대한 자세한 내용은 주석과 후행 쉼표 허용을 참조하세요.
후행 쉼표
역직렬화할 때 Newtonsoft.Json
은 기본적으로 후행 쉼표를 무시합니다. 또한 여러 개의 후행 쉼표를 무시합니다(예: [{"Color":"Red"},{"Color":"Green"},,]
). RFC 8259 사양에서 후행 쉼표를 허용하지 않기 때문에 System.Text.Json은 기본적으로 후행 쉼표에 대해 예외를 throw합니다. System.Text.Json
에서 후행 쉼표를 허용하게 만드는 방법은 주석과 후행 쉼표 허용을 참조하세요. 후행 쉼표를 여러 개 허용하는 방법은 없습니다.
변환기 등록 우선 순위
사용자 지정 변환기에 대한 Newtonsoft.Json
등록 우선 순위는 다음과 같습니다.
- 속성의 특성
- 형식의 특성
- 변환기 컬렉션
이 순서는 형식 수준에서 특성을 적용하여 등록된 변환기가 Converters
컬렉션의 사용자 지정 변환기를 재정의한다는 뜻입니다. 두 등록 모두 속성 수준에서 특성에 의해 재정의됩니다.
사용자 지정 변환기에 대한 System.Text.Json 등록 우선 순위는 다음과 같이 다릅니다.
- 속성의 특성
- Converters 컬렉션
- 형식의 특성
여기서 Converters
컬렉션의 사용자 지정 변환기가 형식 수준에서 특성을 재정의한다는 차이가 있습니다. 이 우선 순위 순서의 숨은 의도는 런타임 변경이 디자인 타임 선택 항목을 재정의하도록 하는 것입니다. 우선 순위를 변경할 수 있는 방법은 없습니다.
사용자 지정 변환기 등록에 대한 자세한 내용은 사용자 지정 변환기 등록을 참조하세요.
최대 깊이
Newtonsoft.Json
의 최신 버전은 기본적으로 최대 깊이 제한이 64입니다. System.Text.Json도 기본 제한은 64이며, JsonSerializerOptions.MaxDepth를 설정하여 구성할 수 있습니다.
ASP.NET Core를 사용하여 간접적으로 System.Text.Json
를 사용하는 경우 기본 최대 깊이 제한은 32입니다. 기본값은 모델 바인딩과 동일하며 JsonOptions 클래스에 설정됩니다.
JSON 문자열(속성 이름 및 문자열 값)
역직렬화할 때 Newtonsoft.Json
은 큰따옴표/작은따옴표로 묶은 속성 이름 또는 따옴표 없는 속성 이름을 허용합니다. 큰따옴표 또는 작은따옴표로 묶은 문자열 값을 허용합니다. 예를 들어 Newtonsoft.Json
은 다음 JSON을 허용합니다.
{
"name1": "value",
'name2': "value",
name3: 'value'
}
System.Text.Json
은 큰따옴표로 묶은 속성 이름과 문자열 값만 허용합니다. RFC 8259 사양에서 이 형식을 요구하며 유일하게 유효한 JSON으로 간주되는 형식이기 때문입니다.
작은따옴표로 묶은 값은 다음 메시지와 함께 JsonException을 반환합니다.
''' is an invalid start of a value.
문자열 속성에 문자열이 아닌 값 허용
Newtonsoft.Json
은 형식 문자열의 속성으로 역직렬화할 때 숫자 또는 리터럴 true
및 false
처럼 문자열이 아닌 값을 허용합니다. 아래는 Newtonsoft.Json
이 성공적으로 다음 클래스로 역직렬화하는 JSON 예제입니다.
{
"String1": 1,
"String2": true,
"String3": false
}
public class ExampleClass
{
public string String1 { get; set; }
public string String2 { get; set; }
public string String3 { get; set; }
}
System.Text.Json
은 문자열이 아닌 값을 문자열 속성으로 역직렬화하지 않습니다. 문자열 필드에 대해 문자열이 아닌 값을 받으면 다음 메시지와 함께 JsonException이 반환됩니다.
The JSON value could not be converted to System.String.
JsonSerializer를 사용하는 시나리오
다음 시나리오는 기본 제공 기능에서 지원되지 않지만 해결이 가능합니다. 해결 방법은 사용자 지정 변환기이며, 사용자 지정 변환기는 Newtonsoft.Json
기능과의 완전한 패리티를 제공하지 않을 수 있습니다. 그 중 일부는 샘플 코드가 예제로 제공됩니다. 이러한 Newtonsoft.Json
기능을 사용하는 경우 마이그레이션을 수행하려면 .NET 개체 모델 또는 기타 코드 변경 내용을 수정해야 합니다.
다음 몇몇 시나리오는 해결 방법이 실용적이지 않거나 가능하지 않습니다. 이러한 Newtonsoft.Json
기능을 사용하는 경우 중요한 변경 없이는 마이그레이션을 수행할 수 없습니다.
따옴표 안에 숫자를 허용하거나 씁니다.
Newtonsoft.Json
은 JSON 문자열로 표시되는(따옴표로 묶은) 숫자를 직렬화 또는 역직렬화할 수 있습니다. 예를 들어 {"DegreesCelsius":23}
대신 {"DegreesCelsius":"23"}
을 허용할 수 있습니다. System.Text.Json에서 이 동작을 사용하도록 설정하려면 JsonSerializerOptions.NumberHandling을 WriteAsString 또는 AllowReadingFromString으로 설정하거나 JsonNumberHandling 특성을 사용합니다.
ASP.NET Core를 사용하여 간접적으로 System.Text.Json
을 사용하는 경우 Newtonsoft.Json
과 같은 동작을 얻기 위해 아무것도 할 필요가 없습니다. ASP.NET Core는 System.Text.Json
을 사용할 때 웹 기본값을 지정하고, 웹 기본값은 따옴표 붙은 숫자를 허용합니다.
자세한 내용은 따옴표 안의 숫자 허용 또는 쓰기를 참조하세요.
역직렬화할 때 사용할 생성자 지정
Newtonsoft.Json
[JsonConstructor]
특성을 사용하면 POCO로 역직렬화할 때 호출할 생성자를 지정할 수 있습니다.
System.Text.Json
에는 JsonConstructor 특성도 있습니다. 자세한 내용은 변경 불가능한 형식 및 레코드를 참조하세요.
조건부로 속성 무시
Newtonsoft.Json
은 직렬화 또는 역직렬화에서 속성을 조건부로 무시하는 여러 가지 방법이 있습니다.
DefaultContractResolver
를 사용하면 임의의 조건에 따라 포함하거나 무시할 속성을 선택할 수 있습니다.JsonSerializerSettings
의NullValueHandling
및DefaultValueHandling
설정을 사용하면 모든 Null 값 또는 기본값 속성을 무시하도록 지정할 수 있습니다.[JsonProperty]
특성의NullValueHandling
및DefaultValueHandling
설정을 사용하면 Null 또는 기본값으로 설정된 경우에 무시할 개별 속성을 지정할 수 있습니다.
System.Text.Json은 직렬화하는 동안 다음과 같은 방법으로 속성이나 필드를 무시할 수 있습니다.
- 속성의 [JsonIgnore] 특성은 직렬화하는 동안 JSON에서 속성을 생략하게 합니다.
- IgnoreReadOnlyProperties 전역 옵션을 사용하면 모든 읽기 전용 속성을 무시할 수 있습니다.
- 필드를 포함하는 경우 JsonSerializerOptions.IgnoreReadOnlyFields 전역 옵션을 통해 모든 읽기 전용 필드를 무시할 수 있습니다.
DefaultIgnoreCondition
전역 옵션을 사용하면 기본값이 있는 모든 값 형식 속성을 무시하거나 null 값이 있는 모든 참조 형식 속성을 무시할 수 있습니다.
또한 .NET 7 이상 버전에서는 임의 조건에 따라 속성을 무시하도록 JSON 계약을 사용자 지정할 수 있습니다. 자세한 내용은 사용자 지정 계약을 참조하세요.
public 및 비-public 필드
Newtonsoft.Json
은 속성뿐 아니라 필드까지 직렬화 및 역직렬화할 수 있습니다.
System.Text.Json에서 JsonSerializerOptions.IncludeFields 전역 설정 또는 JsonInclude 특성을 사용하여 직렬화 또는 역직렬화할 때 public 필드를 포함합니다. 예제는 필드 포함을 참조하세요.
개체 참조 유지 및 루프 처리
기본적으로 Newtonsoft.Json
은 값으로 직렬화합니다. 예를 들어 개체에 두 개의 속성이 있고 두 속성은 동일한 Person
개체에 대한 참조를 포함하는 경우 해당 Person
개체의 속성 값이 JSON에서 중복됩니다.
Newtonsoft.Json
에는 참조로 직렬화할 수 있는 JsonSerializerSettings
에 대한 PreserveReferencesHandling
설정이 있습니다.
- 첫 번째
Person
개체에 대해 만든 JSON에 식별자 메타데이터가 추가됩니다. - 두 번째
Person
개체에 대해 만든 JSON에는 속성 값 대신 해당 식별자에 대한 참조가 포함됩니다.
Newtonsoft.Json
에는 예외를 throw하는 대신 순환 참조를 무시할 수 있는 ReferenceLoopHandling
설정도 있습니다.
System.Text.Json에서 참조를 보존하고 순환 참조를 처리하려면 JsonSerializerOptions.ReferenceHandler을 Preserve로 설정합니다. ReferenceHandler.Preserve
설정은 Newtonsoft.Json
의 PreserveReferencesHandling
= PreserveReferencesHandling.All
과 동일합니다.
ReferenceHandler.IgnoreCycles
옵션에는 Newtonsoft.JsonReferenceLoopHandling.Ignore
와 유사한 동작이 있습니다. 한 가지 차이점은 System.Text.Json 구현이 개체 참조를 무시하는 대신 참조 루프를 null
JSON 토큰으로 대체한다는 것입니다. 자세한 내용은 순환 참조 무시를 참조하세요.
Newtonsoft.JsonReferenceResolver와 마찬가지로 System.Text.Json.Serialization.ReferenceResolver 클래스는 직렬화 및 역직렬화 시 참조를 보존하는 동작을 정의합니다. 파생 클래스를 만들어 사용자 지정 동작을 지정합니다. 예제는 GuidReferenceResolver를 참조하세요.
일부 관련 Newtonsoft.Json
기능은 지원되지 않습니다.
자세한 내용은 참조 보존 및 순환 참조 처리를 참조하세요.
키가 문자열이 아닌 사전
Newtonsoft.Json
및 System.Text.Json
은 모두 Dictionary<TKey, TValue>
형식의 컬렉션을 지원합니다. 그러나 System.Text.Json
에서 TKey
는 사용자 지정 형식이 아닌 기본 형식이어야 합니다. 자세한 내용은 지원되는 키 형식을 참조하세요.
주의
TKey
가 string
이외의 형식으로 지정되는 Dictionary<TKey, TValue>
로 역직렬화하면 소비 애플리케이션에 보안 취약성이 발생할 수 있습니다. 자세한 내용은 dotnet/runtime#4761을 참조하세요.
기본적으로 지원되지 않는 형식
System.Text.Json은 기본적으로 다음 형식을 지원하지 않습니다.
- DataTable 및 관련 형식(자세한 내용은 지원되는 컬렉션 형식 참조)
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple 및 관련 제네릭 형식
기본적으로 지원되지 않는 형식에 대한 사용자 지정 변환기를 구현할 수 있습니다.
다형 직렬화
Newtonsoft.Json
은 다형 직렬화를 자동으로 수행합니다. .NET 7부터 System.Text.Json은 JsonDerivedTypeAttribute 특성을 통한 다형 직렬화를 지원합니다. 자세한 내용은 파생 클래스의 직렬화 속성을 참조하세요.
다형 역직렬화
Newtonsoft.Json
에는 직렬화하는 동안 JSON에 형식 이름 메타데이터를 추가하는 TypeNameHandling
설정이 있습니다. 이 설정은 역직렬화하는 동안 메타데이터를 사용하여 다형 역직렬화를 수행합니다. .NET 7부터 System.Text.Json은 형식 판별자 정보를 사용하여 다형 역직렬화를 수행합니다. 이 메타데이터는 JSON으로 내보낸 다음 역직렬화하는 동안 기본 형식으로 역직렬화할지 또는 파생 형식으로 역직렬화할지 여부를 결정하는 데 사용됩니다. 자세한 내용은 파생 클래스의 직렬화 속성을 참조하세요.
이전 .NET 버전에서 다형 역직렬화를 지원하려면 사용자 지정 변환기를 작성하는 방법의 예제와 같은 변환기를 만듭니다.
문자열 열거형 값 역직렬화
기본적으로 System.Text.Json 문자열 열거형 값은 역직렬화하는 것을 지원하지 않지만, Newtonsoft.Json
는 그렇지 않습니다. 예를 들어 다음 코드는 JsonException을(를) 발생시킵니다.
string json = "{ \"Text\": \"Hello\", \"Enum\": \"Two\" }";
var _ = JsonSerializer.Deserialize<MyObj>(json); // Throws exception.
class MyObj
{
public string Text { get; set; } = "";
public MyEnum Enum { get; set; }
}
enum MyEnum
{
One,
Two,
Three
}
그러나 JsonStringEnumConverter 변환기를 사용하여 문자열 열거형 값의 역직렬화를 사용하도록 설정할 수 있습니다. 자세한 내용은 열거형을 문자열로 참조하세요.
개체 속성 역직렬화
Newtonsoft.Json
은 Object로 역직렬화할 때 다음을 수행합니다.
- JSON 페이로드의 기본 값 형식(
null
제외)을 유추하고 저장된string
,long
,double
,boolean
또는DateTime
을 boxed 개체로 반환합니다. 기본 값은 JSON 숫자, 문자열,true
,false
,null
등의 단일 JSON 값입니다. - JSON 페이로드의 복합 값에 대한
JObject
또는JArray
를 반환합니다. 복합 값은 중괄호({}
) 안에 있는 JSON 키-값 쌍 컬렉션 또는 대괄호([]
) 안에 있는 값 목록입니다. 중괄호 또는 대괄호 안에 있는 속성과 값이 추가 속성 또는 값을 가질 수 있습니다. - 페이로드에
null
JSON 리터럴이 있으면 null 참조를 반환합니다.
System.Text.Json은 Object로 역직렬화할 때마다 기본 값과 복합 값 모두에 대한 boxed JsonElement
를 저장하며, 다음은 그 예입니다.
object
속성object
사전 값object
배열 값- 루트
object
그러나 페이로드에 null
JSON 리터럴이 있으면 System.Text.Json
은 null
을 Newtonsoft.Json
과 같은 방법으로 처리하고 null 참조를 반환합니다.
object
속성에 대한 형식 유추를 구현하려면 사용자 지정 변환기를 작성하는 방법의 예제와 같은 변환기를 만듭니다.
null을 허용하지 않는 형식으로 Null 역직렬화
Newtonsoft.Json
은 는 다음과 같은 시나리오에서 예외를 throw하지 않습니다.
NullValueHandling
이Ignore
로 설정된 경우- 역직렬화를 수행하는 동안 JSON은 null을 허용하지 않는 값 형식에 대해 Null 값을 포함합니다.
동일한 시나리오에서 System.Text.Json은 예외를 throw합니다. (System.Text.Json
에서 해당하는 null 처리 설정은 JsonSerializerOptions.IgnoreNullValues = true
입니다.)
대상 형식을 소유하고 있는 경우 가장 좋은 해결 방법은 문제가 되는 속성을 null 허용으로 만드는 것입니다(예를 들어 int
를 int?
로 변경).
또 다른 해결 방법은 DateTimeOffset
형식의 Null 값을 처리하는 다음 예제처럼 형식에 대한 변환기를 만드는 것입니다.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class DateTimeOffsetNullHandlingConverter : JsonConverter<DateTimeOffset>
{
public override DateTimeOffset Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
reader.TokenType == JsonTokenType.Null
? default
: reader.GetDateTimeOffset();
public override void Write(
Utf8JsonWriter writer,
DateTimeOffset dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue);
}
}
속성에 대한 특성을 사용하거나 Converters 컬렉션에 변환기를 추가하여 이 사용자 지정 변환기를 등록합니다.
참고: 위의 변환기는 기본값을 지정하는 POCO를 Newtonsoft.Json
이 처리하는 방법과는 다르게 Null 값을 처리합니다. 예를 들어 다음 코드가 대상 개체를 보여준다고 가정하겠습니다.
public class WeatherForecastWithDefault
{
public WeatherForecastWithDefault()
{
Date = DateTimeOffset.Parse("2001-01-01");
Summary = "No summary";
}
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}
그리고 앞의 변환기를 사용하여 다음 JSON을 역직렬화한다고 가정합니다.
{
"Date": null,
"TemperatureCelsius": 25,
"Summary": null
}
역직렬화 후 Date
속성에 1/1/0001(default(DateTimeOffset)
)이 있습니다. 즉, 생성자에서 설정한 값이 덮어쓰기 되었습니다. POCO 및 JSON이 동일할 때 Newtonsoft.Json
역직렬화 시 Date
속성에 1/1/2001이 남습니다.
변경할 수 없는 클래스 및 구조체로 역직렬화
Newtonsoft.Json
은 매개 변수가 있는 생성자를 사용할 수 있기 때문에 변경 불가능한 클래스 및 구조체로 역직렬화할 수 있습니다.
System.Text.Json에서 JsonConstructor 특성을 사용하여 매개 변수가 있는 생성자의 사용을 지정합니다. C# 9의 레코드도 변경할 수 없으며, 역직렬화 대상으로 지원됩니다. 자세한 내용은 변경 불가능한 형식 및 레코드를 참조하세요.
필수 속성
Newtonsoft.Json
에서 [JsonProperty]
특성에 대한 Required
를 설정하여 속성을 필수로 지정합니다. 필수로 지정된 속성에 대해 JSON에서 값을 받지 못하면 Newtonsoft.Json
이 예외를 throw합니다.
.NET 7부터 필수 속성에서 C# required
한정자 또는 JsonRequiredAttribute 특성을 사용할 수 있습니다. System.Text.Json은 JSON 페이로드에 표시된 속성에 대한 값이 포함되어 있지 않으면 예외를 throw합니다. 자세한 내용은 필수 속성을 참조하세요.
날짜 형식 지정
Newtonsoft.Json
은 DateTime
및 DateTimeOffset
형식의 속성 직렬화 및 역직렬화 방식을 여러 가지 방법으로 제어할 수 있습니다.
DateTimeZoneHandling
설정을 사용하여 모든DateTime
값을 UTC 날짜로 직렬화할 수 있습니다.DateFormatString
설정 및DateTime
변환기를 사용하여 날짜 문자열의 형식을 사용자 지정할 수 있습니다.
System.Text.Json은 RFC 3339 프로필을 포함하여 ISO 8601-1:2019를 지원합니다. 이 형식은 널리 채택되었으며, 명확하고, 정확하게 왕복합니다. 다른 형식을 사용하려면 사용자 지정 변환기를 만듭니다. 예를 들어 다음 변환기는 표준 시간대 오프셋(/Date(1590863400000-0700)/
또는 /Date(1590863400000)/
와 같은 값)이 포함되거나 포함되지 않은 Unix epoch 형식을 사용하는 JSON을 직렬화 및 역직렬화합니다.
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
|| !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
|| !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
{
throw new JsonException();
}
int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
TimeSpan utcOffset = new(hours * sign, minutes * sign, 0);
return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
TimeSpan utcOffset = value.Offset;
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
}
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
{
throw new JsonException();
}
return s_epoch.AddMilliseconds(unixTime);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
writer.WriteStringValue(formatted);
}
}
자세한 내용은 System.Text.Json에서 DateTime 및 DateTimeOffset 지원을 참조하세요.
콜백
Newtonsoft.Json
은 다음과 같이 직렬화 또는 역직렬화 프로세스의 여러 지점에서 사용자 지정 코드를 실행할 수 있습니다.
- OnDeserializing(개체 역직렬화를 시작할 때)
- OnDeserialized(개체 역직렬화가 완료될 때)
- OnSerializing(개체 직렬화를 시작할 때)
- OnSerialized(개체 직렬화가 완료될 때)
System.Text.Json은 직렬화 및 역직렬화 중에 동일한 알림을 노출합니다. 이를 사용하려면 System.Text.Json.Serialization 네임스페이스에서 다음 인터페이스 중 하나 이상을 구현합니다.
다음은 직렬화 및 역직렬화의 시작과 끝에서 null 속성을 확인하고 메시지를 쓰는 예제입니다.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Callbacks
{
public class WeatherForecast :
IJsonOnDeserializing, IJsonOnDeserialized,
IJsonOnSerializing, IJsonOnSerialized
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
void IJsonOnDeserializing.OnDeserializing() => Console.WriteLine("\nBegin deserializing");
void IJsonOnDeserialized.OnDeserialized()
{
Validate();
Console.WriteLine("Finished deserializing");
}
void IJsonOnSerializing.OnSerializing()
{
Console.WriteLine("Begin serializing");
Validate();
}
void IJsonOnSerialized.OnSerialized() => Console.WriteLine("Finished serializing");
private void Validate()
{
if (Summary is null)
{
Console.WriteLine("The 'Summary' property is 'null'.");
}
}
}
public class Program
{
public static void Main()
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
};
string jsonString = JsonSerializer.Serialize(weatherForecast);
Console.WriteLine(jsonString);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date={weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius={weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary={weatherForecast?.Summary}");
}
}
}
// output:
//Begin serializing
//The 'Summary' property is 'null'.
//Finished serializing
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":null}
//Begin deserializing
//The 'Summary' property is 'null'.
//Finished deserializing
//Date=8/1/2019 12:00:00 AM
//TemperatureCelsius = 25
//Summary=
OnDeserializing
코드는 새 POCO 인스턴스에 액세스할 수 없습니다. 역직렬화를 시작할 때 새 POCO 인스턴스를 조작하려면 이 코드를 POCO 생성자에 배치하세요.
public이 아닌 속성 setter 및 getter
Newtonsoft.Json
은 JsonProperty
특성을 통해 private/internal 속성 setter 및 getter를 사용할 수 있습니다.
System.Text.Json은 JsonInclude 특성을 통해 private 및 internal 속성 setter 및 getter를 지원합니다. 샘플 코드는 public이 아닌 속성 접근자를 참조하세요.
기존 개체 채우기
Newtonsoft.Json
의 JsonConvert.PopulateObject
메서드는 새 인스턴스를 만드는 대신 JSON 문서를 클래스의 기존 인스턴스로 역직렬화합니다. System.Text.Json은 항상 매개 변수 없는 기본 public 생성자를 사용하여 대상 형식의 새 인스턴스를 만듭니다. 사용자 지정 변환기는 기존 인스턴스로 역직렬화할 수 있습니다.
속성을 바꾸지 않고 재사용
.NET 8 System.Text.Json 부터는 초기화된 속성을 바꾸는 대신 다시 사용할 수 있습니다. API 제안에서 읽을 수 있는 동작에는 몇 가지 차이점이 있습니다.
자세한 내용은 초기화된 속성 채우기를 참조하세요.
setter 없이 속성 채우기
.NET 8 System.Text.Json 부터 setter가 없는 속성을 포함하여 채우기 속성을 지원합니다. 자세한 내용은 초기화된 속성 채우기를 참조하세요.
스네이크 표기법 이름 지정 정책
System.Text.Json에는 뱀 케이스에 대한 기본 제공 명명 정책이 포함되어 있습니다. 그러나 일부 입력에는 Newtonsoft.Json
와(과) 몇 가지 동작 차이점이 있습니다. 다음 표에서는 JsonNamingPolicy.SnakeCaseLower 정책을 사용하여 입력을 변환할 때의 몇 가지 차이점을 보여 줍니다.
입력 | Newtonsoft.Json 결과 | System.Text.Json 결과 |
---|---|---|
"AB1" | "a_b1" | "ab1" |
"SHA512Managed" | "sh_a512_managed" | "sha512_managed" |
"abc123DEF456" | "abc123_de_f456" | "abc123_def456" |
"KEBAB-CASE" | "keba_b-_case" | "kebab-case" |
System.Runtime.Serialization 특성
DataContractAttribute, DataMemberAttribute 및 IgnoreDataMemberAttribute 같은 System.Runtime.Serialization 특성을 데이터 계약으로 정의할 수 있습니다. 데이터 계약 은 서비스와 클라이언트 사이에서 교환할 데이터를 추상적으로 설명한 공식 계약입니다. 데이터 계약은 교환을 위해 직렬화되는 속성을 정확하게 정의합니다.
System.Text.Json에는 이러한 특성에 대한 기본 제공 지원이 없습니다. 그러나 .NET 7부터 사용자 지정 형식 확인자를 사용하여 지원을 추가할 수 있습니다. 샘플은 ZCS.DataContractResolver를 참조하세요.
8진수
Newtonsoft.Json
은 선행 0이 있는 숫자를 8진수로 처리합니다. RFC 8259 사양에서 선행 0을 허용하지 않으므로 System.Text.Json은 선행 0을 허용하지 않습니다.
누락된 멤버 처리
JSON이 대상 형식에 없는 속성을 포함하는 경우 역직렬화 중에 예외를 발생시키도록 Newtonsoft.Json
(을)를 구성할 수 있습니다. 기본적으로, System.Text.Json은 [JsonExtensionData] 특성을 사용하는 경우를 제외하고 JSON의 추가 속성을 무시합니다.
.NET 8 이상 버전에서는 다음 방법 중 하나를 사용하여 매핑되지 않은 JSON 속성을 건너뛰거나 허용하지 않는지 여부에 대한 기본 설정을 지정할 수 있습니다.
- 역직렬화할 형식에 JsonUnmappedMemberHandlingAttribute 특성을 적용합니다.
- 기본 설정을 전역적으로 설정하려면 JsonSerializerOptions.UnmappedMemberHandling 속성을 설정합니다. 또는 원본 생성의 경우 JsonSourceGenerationOptionsAttribute.UnmappedMemberHandling 속성을 설정하고 JsonSerializerContext 클래스에 특성을 적용합니다.
- JsonTypeInfo.UnmappedMemberHandling 속성을 사용자 지정합니다.
JsonObjectAttribute
Newtonsoft.Json
에는 직렬화되는 멤버, null
값 처리 방법 및 모든 멤버가 필요한지 여부를 제어하기 위해 형식 수준에서 적용할 수 있는 JsonObjectAttribute
특성이 있습니다. System.Text.Json에는 형식에 적용할 수 있는 동일한 특성이 없습니다. null
값 처리와 같은 일부 동작의 경우 전역 JsonSerializerOptions 또는 각 속성에서 개별적으로 동일한 동작을 구성할 수 있습니다.
모든 null
속성을 무시하도록 지정하는 데 사용하는 Newtonsoft.Json.JsonObjectAttribute
(으)로 다음 예제를 고려합니다.
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }
System.Text.Json에서 모든 형식 및 속성에 대한 동작을 설정할 수 있습니다.
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string json = JsonSerializer.Serialize<Person>(person, options);
또는 각 속성에 대한 동작을 별도로 설정할 수 있습니다.
public class Person
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Age { get; set; }
}
다음으로, 모든 멤버 속성이 JSON에 있어야 하도록 지정하는 데 Newtonsoft.Json.JsonObjectAttribute
(을)를 사용하는 다음 예제를 고려합니다.
[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }
C# required
한정자 또는 JsonRequiredAttribute 각 속성에 추가하여 System.Text.Json의 동일한 동작을 수행할 수 있습니다. 자세한 내용은 필수 속성을 참조하세요.
public class Person
{
[JsonRequired]
public string? Name { get; set; }
public required int? Age { get; set; }
}
TraceWriter
Newtonsoft.Json
은 직렬화 또는 역직렬화에서 생성된 로그를 살펴보는 TraceWriter
를 사용하여 디버그할 수 있습니다. System.Text.Json은 로깅을 수행하지 않습니다.
JsonDocument 및 JsonElement과 JToken(예: JObject, JArray)의 비교
System.Text.Json.JsonDocument은 기존 JSON 페이로드의 읽기 전용 DOM(문서 개체 모델)을 구문 분석하고 빌드하는 기능을 제공합니다. DOM은 JSON 페이로드의 데이터에 대한 임의 액세스를 제공합니다. 페이로드를 구성하는 JSON 요소는 JsonElement 형식을 통해 액세스할 수 있습니다. JsonElement
형식은 JSON 텍스트를 일반적인 .NET 형식으로 변환하는 API를 제공합니다. JsonDocument
는 RootElement 속성을 노출합니다.
.NET 6부터 System.Text.Json.Nodes 네임스페이스의 JsonNode 형식 및 기타 형식을 사용하여 기존 JSON 페이로드에서 변경 가능한 DOM을 구문 분석하고 빌드할 수 있습니다. 자세한 내용은 JsonNode
사용을 참조하세요.
JsonDocument는 IDisposable
JsonDocument
는 데이터의 메모리 내 보기를 풀링된 버퍼에 빌드합니다. 따라서 Newtonsoft.Json
의 JObject
또는 JArray
와 달리, JsonDocument
형식은 IDisposable
을 구현하며 using 블록 내에서 사용해야 합니다. 자세한 내용은 JsonDocument는 IDisposable을 참조하세요.
JsonDocument는 읽기 전용
System.Text.Json DOM은 JSON 요소를 추가, 제거 또는 수정할 수 없습니다. 이렇게 설계한 이유는 성능을 향상하고 일반 JSON 페이로드 크기를 구문 분석할 때 할당을 줄이는(즉, < 1MB) 것입니다.
JsonElement는 공용 구조체
JsonDocument
는 RootElement
를 JSON 요소를 포함하는 공용 구조체 형식인 JsonElement 형식의 속성으로 노출합니다. Newtonsoft.Json
은 JObject
, JArray
, JToken
등의 전용 계층형 형식을 사용합니다. JsonElement
는 검색하고 열거할 수 있으며, JsonElement
를 사용하여 JSON 요소를 .NET 형식으로 구체화할 수 있습니다.
.NET 6부터 JsonNode 형식 및 System.Text.Json.Nodes 네임스페이스에서 JObject
, JArray
및 JToken
에 해당하는 형식을 사용할 수 있습니다. 자세한 내용은 JsonNode
사용을 참조하세요.
하위 요소의 JsonDocument 및 JsonElement를 검색하는 방법
Newtonsoft.Json
에서 JObject
또는 JArray
를 사용하여 JSON 토큰을 검색하면 일부 사전을 조회하기 때문에 비교적 속도가 빠릅니다. 그에 비해, JsonElement
에서 검색하려면 속성을 순차적으로 검색해야 하므로 상대적으로 느립니다(예: TryGetProperty
를 사용하는 경우). System.Text.Json은 조회 시간이 아닌 초기 구문 분석 시간을 최소화하도록 설계되었습니다. 자세한 내용은 하위 요소의 JsonDocument 및 JsonElement를 검색하는 방법을 참조하세요.
Utf8JsonReader vs. JsonTextReader
System.Text.Json.Utf8JsonReader는 ReadOnlySpan<byte> 또는 ReadOnlySequence<byte>에서 읽어온 UTF-8 인코딩 JSON 텍스트를 위한 고성능, 저할당, 전달 전용 판독기입니다. Utf8JsonReader
는 사용자 지정 구문 분석기 및 역직렬 변환기를 빌드하는 데 활용할 수 있는 하위 수준 형식입니다.
Utf8JsonReader는 ref struct
Newtonsoft.Json
의 JsonTextReader
는 클래스입니다. Utf8JsonReader
형식은 ref 구조체라는 점에서 다릅니다. 자세한 내용은 Utf8JsonReader에 대한 ref 구조체 제한을 참조하세요.
Null 값을 null 허용 값 형식으로 읽기
Newtonsoft.Json
은 bool?
을 반환하도록 하기 위해 Null
TokenType
를 처리하는 ReadAsBoolean
과 같은 Nullable<T>를 반환하는 API를 제공합니다. 기본 제공 System.Text.Json
API는 null을 허용하지 않는 값 형식만 반환합니다. 자세한 내용은 nullable 값 형식으로 null 값 읽기를 참조하세요.
JSON 읽기를 위한 다중 대상
특정 대상 프레임워크에 Newtonsoft.Json
을 계속 사용해야 하는 경우 다중 대상을 지정하여 두 가지를 구현할 수 있습니다. 그러나 이 방법은 간단하지 않으며 #ifdefs
및 원본 복제가 필요합니다. 최대한 많은 코드를 공유하는 한 가지 방법은 Utf8JsonReader 및 Newtonsoft.Json.JsonTextReader
주위에 ref struct
래퍼를 만드는 것입니다. 이 래퍼는 동작의 차이를 격리하면서 공개 노출 영역을 통합합니다. 이렇게 하면 새 형식을 참조로 전달하는 것과 함께 변경 내용을 주로 형식 생성으로 격리할 수 있습니다. 다음은 Microsoft.Extensions.DependencyModel 라이브러리가 따르는 패턴입니다.
Utf8JsonWriter vs. JsonTextWriter
System.Text.Json.Utf8JsonWriter은 String
, Int32
및 DateTime
과 같은 일반적인 .NET 형식에서 UTF-8 인코딩 JSON 텍스트를 쓸 수 있는 고성능 방법을 제공합니다. writer는 사용자 지정 직렬 변환기를 빌드하는 데 사용할 수 있는 하위 수준 형식입니다.
원시 값 작성
Newtonsoft.Json
에는 값이 필요한 원시 JSON을 작성하는 WriteRawValue
메서드가 있습니다. System.Text.Json에는 직접적으로 해당하는 항목 Utf8JsonWriter.WriteRawValue가 없습니다. 자세한 내용은 원시 JSON 작성을 참조하세요.
JSON 형식 사용자 지정
JsonTextWriter
에는 다음과 같은 설정이 있으며, Utf8JsonWriter에는 해당 기능이 없습니다.
- QuoteChar - 문자열 값을 묶는 데 사용할 문자를 지정합니다.
Utf8JsonWriter
는 항상 큰따옴표를 사용합니다. - QuoteName - 속성 이름을 따옴표로 묶을지 여부를 지정합니다.
Utf8JsonWriter
는 항상 속성 이름을 따옴표로 묶습니다.
.NET 9부터는 JsonWriterOptions 구조체에서 노출하는 옵션을 사용하기 위해 Utf8JsonWriter의 들여쓰기 문자와 크기를 사용자 지정할 수 있습니다.
JsonTextWriter
에는 다음과 같은 설정이 있으며, Utf8JsonWriter
에는 해당 기능이 없습니다.
- Indentation - 들여쓸 문자 수를 지정합니다.
Utf8JsonWriter
는 항상 2자 들여쓰기를 합니다. - IndentChar - 들여쓰기에 사용할 문자를 지정합니다.
Utf8JsonWriter
는 항상 공백을 사용합니다. - QuoteChar - 문자열 값을 묶는 데 사용할 문자를 지정합니다.
Utf8JsonWriter
는 항상 큰따옴표를 사용합니다. - QuoteName - 속성 이름을 따옴표로 묶을지 여부를 지정합니다.
Utf8JsonWriter
는 항상 속성 이름을 따옴표로 묶습니다.
이러한 방법으로 Utf8JsonWriter
에서 생성된 JSON을 사용자 지정할 수 있는 해결 방법은 없습니다.
Timespan, Uri 또는 char 값 쓰기
JsonTextWriter
는 TimeSpan, Uri 및 char 값에 대한 WriteValue
메서드를 제공합니다. Utf8JsonWriter
에는 이에 해당하는 메서드가 없습니다. 그 대신 이러한 값을 문자열로 포맷하고(예를 들어 ToString()
을 호출) WriteStringValue를 호출할 수 있습니다.
JSON 작성을 위한 다중 대상
특정 대상 프레임워크에 Newtonsoft.Json
을 계속 사용해야 하는 경우 다중 대상을 지정하여 두 가지를 구현할 수 있습니다. 그러나 이 방법은 간단하지 않으며 #ifdefs
및 원본 복제가 필요합니다. 최대한 많은 코드를 공유하는 한 가지 방법은 Utf8JsonWriter 및 Newtonsoft.Json.JsonTextWriter
주위에 래퍼를 만드는 것입니다. 이 래퍼는 동작의 차이를 격리하면서 공개 노출 영역을 통합합니다. 이를 통해 변경 내용을 주로 형식 생성으로 격리할 수 있습니다. Microsoft.Extensions.DependencyModel 라이브러리는 다음 패턴을 따릅니다.
TypeNameHandling.All이 지원되지 않음
System.Text.Json
에서 TypeNameHandling.All
동등 기능을 제외한 결정은 의도적인 것이었습니다. JSON 페이로드가 자체 형식 정보를 지정하도록 허용하는 것은 웹 애플리케이션에서 일반적인 취약성 소스입니다. 특히 Newtonsoft.Json
을 TypeNameHandling.All
로 구성하면 원격 클라이언트가 JSON 페이로드 자체에 전체 실행 파일 애플리케이션을 포함할 수 있으므로 역직렬화 중에 웹 애플리케이션이 포함된 코드를 추출하고 실행할 수 있습니다. 자세한 내용은 Friday the 13th JSON 공격 PowerPoint 및 Friday the 13th JSON 공격 세부 정보를 참조하세요.
JSON 경로 쿼리가 지원되지 않음
JsonDocument
DOM은 JSON 경로를 사용한 쿼리를 지원하지 않습니다.
JsonNode DOM에서 각 JsonNode
인스턴스에는 해당 노드에 대한 경로를 반환하는 GetPath
메서드가 있습니다. 그러나 JSON 경로 쿼리 문자열을 기반으로 쿼리를 처리하는 기본 제공 API는 없습니다.
자세한 내용은 dotnet/runtime #31068 GitHub 이슈를 참조하세요.
일부 제한을 구성할 수 없음
System.Text.Json은 최대 토큰 크기 문자(166MB) 및 base 64(125MB)와 같이 일부 값에 대해 변경할 수 없는 제한을 설정합니다. 자세한 내용은 JsonConstants
에서 소스 코드 및 GitHub 이슈 dotnet/runtime #39953을 참조하세요.
NaN, Infinity, -Infinity
Newtonsoft는 NaN
, Infinity
및 -Infinity
JSON 문자열 토큰을 구문 분석합니다. System.Text.Json에서는 JsonNumberHandling.AllowNamedFloatingPointLiterals(을)를 사용합니다. 이 설정을 사용하는 방법에 대한 자세한 내용은 따옴표 안에 숫자 허용 또는 쓰기를 참조하세요.
GitHub Copilot를 사용하여 마이그레이션
IDE 내에서 코드를 변환하기 위해 GitHub Copilot에서 코딩 도움말을 받을 수 있습니다.
Visual Studio 2022 버전 17.8 이상을 사용하는 경우 AI 기반 Visual Studio의 GitHub Copilot를 사용하여 Newtonsoft.Json
코드를 System.Text.Json
(으)로 마이그레이션할 수 있습니다. 다음 예제와 같이 질문과 코드를 제출하여 Copilot 채팅 창에서 프롬프트로 변환합니다.
참고 항목
GitHub Copilot는 AI를 통해 구동되므로 예상치 못한 실수가 발생할 수 있습니다. 생성된 코드 또는 제안을 확인해야 합니다. GitHub Copilot의 일반적인 사용, 제품 영향, 사용자 감독 및 개인 정보에 대한 자세한 내용은 GitHub Copilot FAQ를 참조하세요.
Copilot 채팅에 대한 프롬프트 예시
convert the following code to use System.Text.Json
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonConvert.SerializeObject(product);
Console.WriteLine(output);
Copilot 채팅 응답 예시
To convert the code to use System.Text.Json, you can use the JsonSerializer class. Here's the updated code:
using System;
using System.Text.Json;
public class Product
{
public string Name { get; set; }
public DateTime ExpiryDate { get; set; }
public decimal Price { get; set; }
public string[] Sizes { get; set; }
}
public class Program
{
public static void Main()
{
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonSerializer.Serialize(product);
Console.WriteLine(output);
}
}
This code uses System.Text.Json.JsonSerializer.Serialize to convert the Product object to a JSON string.
결과는 이러한 예시 응답에 표시된 것과 다를 수 있습니다. AI 모델은 비결정적이므로 동일한 질문을 할 때 다른 응답을 반환할 수 있습니다. 이는 시간이 지남에 따라 추가적인 학습과 적응, 언어의 차이, 채팅 기록과 같은 상황의 변화 등으로 인해 발생할 수 있습니다.
슬래시 명령, 참조 및 스레드와 같은 채팅 기능을 사용하여 의도를 설정하고 범위가 지정된 컨텍스트에서 더 나은 답변을 얻을 수 있습니다.
예를 들어 코드 파일 filename
이(가) IDE에서 열려 있는 경우 "#filename
을(를) System.Text.Json
(으)로 변환"이라는 Copilot 채팅 프롬프트에서 파일을 참조할 수 있습니다. 또는 채팅 창 또는 인라인 채팅에서 "@workspace
을(를) System.Text.Json
(으)로 변환"을 사용하여 솔루션을 참조할 수 있습니다.
추가 리소스
.NET