Newtonsoft.Json から System.Text.Json に移行する方法How to migrate from Newtonsoft.Json to System.Text.Json

この記事では、Newtonsoft.Json から System.Text.Json に移行する方法を示します。This article shows how to migrate from Newtonsoft.Json to System.Text.Json.

System.Text.Json 名前空間は、JavaScript Object Notation (JSON) との間でのシリアル化と逆シリアル化の機能を提供します。The System.Text.Json namespace provides functionality for serializing to and deserializing from JavaScript Object Notation (JSON). System.Text.Json ライブラリは、.NET Core 3.1 以降のバージョン用のランタイムに含まれています。The System.Text.Json library is included in the runtime for .NET Core 3.1 and later versions. その他のターゲット フレームワークの場合は、System.Text.Json NuGet パッケージをインストールします。For other target frameworks, install the System.Text.Json NuGet package. このパッケージで以下がサポートされます。The package supports:

  • .NET Standard 2.0 以降のバージョン.NET Standard 2.0 and later versions
  • .NET Framework 4.7.2 以降のバージョン.NET Framework 4.7.2 and later versions
  • .NET Core 2.0、2.1、および 2.2.NET Core 2.0, 2.1, and 2.2

System.Text.Json は、主にパフォーマンス、セキュリティ、標準への準拠に焦点を当てています。System.Text.Json focuses primarily on performance, security, and standards compliance. これには既定の動作について重要な違いがいくつかあり、Newtonsoft.Json との機能パリティを持つことがこの目的ではありません。It has some key differences in default behavior and doesn't aim to have feature parity with Newtonsoft.Json. 一部のシナリオでは、System.Text.Json に組み込み機能がなくても、推奨される回避策があります。For some scenarios, System.Text.Json has no built-in functionality, but there are recommended workarounds. それ以外のシナリオでは、回避策は実用的ではありません。For other scenarios, workarounds are impractical. お使いのアプリケーションで、欠如している機能を利用する必要がある場合は、ご自分のシナリオのサポートを追加できるかどうかを確認するために、問題を申請することを検討してください。If your application depends on a missing feature, consider filing an issue to find out if support for your scenario can be added.

この記事のほとんどの内容は、JsonSerializer API の使用方法に関するものですが、JsonDocument (ドキュメント オブジェクト モデル: DOM を表します)、Utf8JsonReaderUtf8JsonWriter の型の使用方法に関するガイダンスも含まれています。Most of this article is about how to use the JsonSerializer API, but it also includes guidance on how to use the JsonDocument (which represents the Document Object Model or DOM), Utf8JsonReader, and Utf8JsonWriter types.

Newtonsoft.Json と System.Text.Json の相違点の表Table of differences between Newtonsoft.Json and System.Text.Json

次の表は、Newtonsoft.Json の機能と、それと同等の System.Text.Json の機能を一覧にしたものです。The following table lists Newtonsoft.Json features and System.Text.Json equivalents. 同等機能は次のカテゴリに分けられます。The equivalents fall into the following categories:

  • 組み込み機能によってサポートされています。Supported by built-in functionality. System.Text.Json で同様の動作を得るには、属性またはグローバル オプションの使用が必要になる場合があります。Getting similar behavior from System.Text.Json may require the use of an attribute or global option.
  • サポートされていませんが、回避策を適用できます。Not supported, workaround is possible. 回避策とはカスタム コンバーターのことですが、これによって Newtonsoft.Json の機能との完全なパリティが得られるとは限りません。The workarounds are custom converters, which may not provide complete parity with Newtonsoft.Json functionality. これらの一部については、サンプル コードが例として提供されます。For some of these, sample code is provided as examples. Newtonsoft.Json のこれらの機能を利用する必要がある場合、移行するには、.NET オブジェクト モデルに対する変更やその他のコード変更が必要になります。If you rely on these Newtonsoft.Json features, migration will require modifications to your .NET object models or other code changes.
  • サポートされていません。回避策は実用的でないか不可能です。Not supported, workaround is not practical or possible. Newtonsoft.Json のこれらの機能を利用する必要がある場合、移行を可能にするには大幅な変更が必要です。If you rely on these Newtonsoft.Json features, migration will not be possible without significant changes.
Newtonsoft.Json の機能Newtonsoft.Json feature System.Text.Json での同等機能System.Text.Json equivalent
既定での大文字と小文字の区別のない逆シリアル化Case-insensitive deserialization by default ✔️ PropertyNameCaseInsensitive グローバル設定✔️ PropertyNameCaseInsensitive global setting
キャメルケースのプロパティ名Camel-case property names ✔️ PropertyNamingPolicy グローバル設定✔️ PropertyNamingPolicy global setting
最小限の文字のエスケープMinimal character escaping ✔️ 厳密な文字エスケープ、構成可能✔️ Strict character escaping, configurable
NullValueHandling.Ignore グローバル設定NullValueHandling.Ignore global setting ✔️ DefaultIgnoreCondition グローバル オプション✔️ DefaultIgnoreCondition global option プロパティを条件付きで無視するConditionally ignore a property
コメントを許可するAllow comments ✔️ ReadCommentHandling グローバル設定✔️ ReadCommentHandling global setting
末尾のコンマを許可するAllow trailing commas ✔️ AllowTrailingCommas グローバル設定✔️ AllowTrailingCommas global setting
カスタム コンバーターの登録Custom converter registration ✔️ 優先順位の順序が異なる✔️ Order of precedence differs
既定では最大深度がないNo maximum depth by default ✔️ 既定の最大深度は 64、構成可能✔️ Default maximum depth 64, configurable
PreserveReferencesHandling グローバル設定PreserveReferencesHandling global setting ✔️ ReferenceHandling グローバル設定✔️ ReferenceHandling global setting
ReferenceLoopHandling グローバル設定ReferenceLoopHandling global setting ✔️ ReferenceHandling グローバル設定✔️ ReferenceHandling global setting
引用符で囲まれた数値をシリアル化または逆シリアル化するSerialize or deserialize numbers in quotes ✔️ NumberHandling グローバル設定、[JsonNumberHandling] 属性✔️ NumberHandling global setting, [JsonNumberHandling] attribute
不変のクラスと構造体への逆シリアル化Deserialize to immutable classes and structs ✔️ JsonConstructor、C# 9 のレコード✔️ JsonConstructor, C# 9 Records
フィールドのサポートSupport for fields ✔️ IncludeFields グローバル設定、[JsonInclude] 属性✔️ IncludeFields global setting, [JsonInclude] attribute
DefaultValueHandling グローバル設定DefaultValueHandling global setting ✔️ DefaultIgnoreCondition グローバル設定✔️ DefaultIgnoreCondition global setting
[JsonProperty] での NullValueHandling の設定NullValueHandling setting on [JsonProperty] ✔️ JsonIgnore 属性✔️ JsonIgnore attribute
[JsonProperty] での DefaultValueHandling の設定DefaultValueHandling setting on [JsonProperty] ✔️ JsonIgnore 属性✔️ JsonIgnore attribute
文字列以外のキーを含む Dictionary を逆シリアル化するDeserialize Dictionary with non-string key ✔️ Supported✔️ Supported
非パブリック プロパティのセッターとゲッターのサポートSupport for non-public property setters and getters ✔️ JsonInclude 属性✔️ JsonInclude attribute
[JsonConstructor] 属性[JsonConstructor] attribute ✔️ [JsonConstructor] 属性✔️ [JsonConstructor] attribute
さまざまな型のサポートSupport for a broad range of types ⚠️ 一部の型にはカスタム コンバーターが必要である⚠️ Some types require custom converters
ポリモーフィックなシリアル化Polymorphic serialization ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
ポリモーフィックな逆シリアル化Polymorphic deserialization ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
推論された型を object のプロパティに逆シリアル化するDeserialize inferred type to object properties ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
JSON の null リテラルを null 非許容値の型に逆シリアル化するDeserialize JSON null literal to non-nullable value types ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
[JsonProperty] 属性での Required の設定Required setting on [JsonProperty] attribute ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
プロパティを無視するための DefaultContractResolverDefaultContractResolver to ignore properties ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
DateTimeZoneHandlingDateFormatString の設定DateTimeZoneHandling, DateFormatString settings ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
コールバックCallbacks ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
JsonConvert.PopulateObject メソッドJsonConvert.PopulateObject method ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
ObjectCreationHandling グローバル設定ObjectCreationHandling global setting ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
セッターなしでコレクションに追加するAdd to collections without setters ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
System.Runtime.Serialization 属性のサポートSupport for System.Runtime.Serialization attributes サポートされていないNot supported
MissingMemberHandling グローバル設定MissingMemberHandling global setting サポートされていないNot supported
引用符なしのプロパティ名を許可するAllow property names without quotes サポートされていないNot supported
文字列値を囲む単一引用符を許可するAllow single quotes around string values サポートされていないNot supported
文字列のプロパティに対して文字列ではない JSON 値を許可するAllow non-string JSON values for string properties サポートされていないNot supported
Newtonsoft.Json の機能Newtonsoft.Json feature System.Text.Json での同等機能System.Text.Json equivalent
既定での大文字と小文字の区別のない逆シリアル化Case-insensitive deserialization by default ✔️ PropertyNameCaseInsensitive グローバル設定✔️ PropertyNameCaseInsensitive global setting
キャメルケースのプロパティ名Camel-case property names ✔️ PropertyNamingPolicy グローバル設定✔️ PropertyNamingPolicy global setting
最小限の文字のエスケープMinimal character escaping ✔️ 厳密な文字エスケープ、構成可能✔️ Strict character escaping, configurable
NullValueHandling.Ignore グローバル設定NullValueHandling.Ignore global setting ✔️ IgnoreNullValues グローバル オプション✔️ IgnoreNullValues global option
コメントを許可するAllow comments ✔️ ReadCommentHandling グローバル設定✔️ ReadCommentHandling global setting
末尾のコンマを許可するAllow trailing commas ✔️ AllowTrailingCommas グローバル設定✔️ AllowTrailingCommas global setting
カスタム コンバーターの登録Custom converter registration ✔️ 優先順位の順序が異なる✔️ Order of precedence differs
既定では最大深度がないNo maximum depth by default ✔️ 既定の最大深度は 64、構成可能✔️ Default maximum depth 64, configurable
さまざまな型のサポートSupport for a broad range of types ⚠️ 一部の型にはカスタム コンバーターが必要である⚠️ Some types require custom converters
文字列を数値として逆シリアル化するDeserialize strings as numbers ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
文字列以外のキーを含む Dictionary を逆シリアル化するDeserialize Dictionary with non-string key ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
ポリモーフィックなシリアル化Polymorphic serialization ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
ポリモーフィックな逆シリアル化Polymorphic deserialization ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
推論された型を object のプロパティに逆シリアル化するDeserialize inferred type to object properties ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
JSON の null リテラルを null 非許容値の型に逆シリアル化するDeserialize JSON null literal to non-nullable value types ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
不変のクラスと構造体への逆シリアル化Deserialize to immutable classes and structs ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
[JsonConstructor] 属性[JsonConstructor] attribute ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
[JsonProperty] 属性での Required の設定Required setting on [JsonProperty] attribute ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
[JsonProperty] 属性での NullValueHandling の設定NullValueHandling setting on [JsonProperty] attribute ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
[JsonProperty] 属性での DefaultValueHandling の設定DefaultValueHandling setting on [JsonProperty] attribute ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
DefaultValueHandling グローバル設定DefaultValueHandling global setting ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
プロパティを無視するための DefaultContractResolverDefaultContractResolver to ignore properties ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
DateTimeZoneHandlingDateFormatString の設定DateTimeZoneHandling, DateFormatString settings ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
コールバックCallbacks ⚠️ サポートされていない、回避策、サンプル⚠️ Not supported, workaround, sample
パブリックおよび非パブリック フィールドのサポートSupport for public and non-public fields ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
非パブリック プロパティのセッターとゲッターのサポートSupport for non-public property setters and getters ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
JsonConvert.PopulateObject メソッドJsonConvert.PopulateObject method ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
ObjectCreationHandling グローバル設定ObjectCreationHandling global setting ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
セッターなしでコレクションに追加するAdd to collections without setters ⚠️ サポートされていない、回避策⚠️ Not supported, workaround
PreserveReferencesHandling グローバル設定PreserveReferencesHandling global setting サポートされていないNot supported
ReferenceLoopHandling グローバル設定ReferenceLoopHandling global setting サポートされていないNot supported
System.Runtime.Serialization 属性のサポートSupport for System.Runtime.Serialization attributes サポートされていないNot supported
MissingMemberHandling グローバル設定MissingMemberHandling global setting サポートされていないNot supported
引用符なしのプロパティ名を許可するAllow property names without quotes サポートされていないNot supported
文字列値を囲む単一引用符を許可するAllow single quotes around string values サポートされていないNot supported
文字列のプロパティに対して文字列ではない JSON 値を許可するAllow non-string JSON values for string properties サポートされていないNot supported

これは Newtonsoft.Json 機能の包括的なリストではありません。This is not an exhaustive list of Newtonsoft.Json features. この一覧には、GitHub の問題または StackOverflow の投稿でリクエストされたシナリオの多くが含まれています。The list includes many of the scenarios that have been requested in GitHub issues or StackOverflow posts. ここに一覧表示されたシナリオのうち、現在サンプル コードがないシナリオの 1 つに回避策を実装する場合、およびご自分の解決策を共有する場合は、このページの下部にある [フィードバック] セクションで [このページ] を選択してください。If you implement a workaround for one of the scenarios listed here that doesn't currently have sample code, and if you want to share your solution, select This page in the Feedback section at the bottom of this page. これにより、問題がこのドキュメントの GitHub リポジトリに作成され、このページの [フィードバック] セクションにも記載されます。That creates an issue in this documentation's GitHub repo and lists it in the Feedback section on this page too.

Newtonsoft.Json と比較した既定の JsonSerializer の動作の相違点Differences in default JsonSerializer behavior compared to Newtonsoft.Json

既定では System.Text.Json は厳格であり、確定的な動作を重視して、呼び出し元のために推測や解釈は行われません。System.Text.Json is strict by default and avoids any guessing or interpretation on the caller's behalf, emphasizing deterministic behavior. このライブラリは、パフォーマンスとセキュリティを確保するために意図的にこのように設計されています。The library is intentionally designed this way for performance and security. Newtonsoft.Json は既定で柔軟性を持っています。Newtonsoft.Json is flexible by default. 設計上のこの基本的な違いが、既定の動作における次のような固有の相違点の多くで、その背景にあります。This fundamental difference in design is behind many of the following specific differences in default behavior.

大文字と小文字の区別のない逆シリアル化Case-insensitive deserialization

逆シリアル化中、Newtonsoft.Json では、大文字と小文字の区別のないプロパティ名の照合が既定で行われます。During deserialization, Newtonsoft.Json does case-insensitive property name matching by default. System.Text.Json の既定では大文字と小文字が区別されます。完全一致が行われるため、これによってパフォーマンスが向上します。The System.Text.Json default is case-sensitive, which gives better performance since it's doing an exact match. 大文字と小文字の区別のない照合の実行方法については、「大文字と小文字を区別しないプロパティ照合」を参照してください。For information about how to do case-insensitive matching, see Case-insensitive property matching.

ASP.NET Core を使用して System.Text.Json を間接的に使用している場合、Newtonsoft.Json のような動作を得るために何かをする必要はありません。If you're using System.Text.Json indirectly by using ASP.NET Core, you don't need to do anything to get behavior like Newtonsoft.Json. ASP.NET Core では、System.Text.Json を使用するときに、Camel 形式のプロパティ名および大文字と小文字を区別しない照合のための設定が指定されます。ASP.NET Core specifies the settings for camel-casing property names and case-insensitive matching when it uses System.Text.Json.

ASP.NET Core を使用すると、引用符で囲まれた数値を既定で逆シリアル化することもできます。ASP.NET Core also enables deserializing quoted numbers by default.

最小限の文字のエスケープMinimal character escaping

シリアル化中、Newtonsoft.Json では文字をエスケープしないままにすることが比較的許容されています。During serialization, Newtonsoft.Json is relatively permissive about letting characters through without escaping them. つまり、xxxx が文字のコード ポイントである場合、その文字が \uxxxx には置き換えられません。That is, it doesn't replace them with \uxxxx where xxxx is the character's code point. 文字がエスケープされる場合、その文字の前に \ が出力されます (たとえば、"\" になります)。Where it does escape them, it does so by emitting a \ before the character (for example, " becomes \"). System.Text.Json の場合、既定でより多くの文字がエスケープされ、クロスサイト スクリプティング (XSS) や情報漏えいの攻撃に対する多層防御保護が実現します。そのために 6 文字のシーケンスが使用されます。System.Text.Json escapes more characters by default to provide defense-in-depth protections against cross-site scripting (XSS) or information-disclosure attacks and does so by using the six-character sequence. System.Text.Json では、既定で ASCII 以外の文字がすべてエスケープされるため、Newtonsoft.JsonStringEscapeHandling.EscapeNonAscii を使用している場合は、何もする必要はありません。System.Text.Json escapes all non-ASCII characters by default, so you don't need to do anything if you're using StringEscapeHandling.EscapeNonAscii in Newtonsoft.Json. また、System.Text.Json では、既定で HTML に影響する文字もエスケープされます。System.Text.Json also escapes HTML-sensitive characters, by default. System.Text.Json の既定の動作をオーバーライドする方法については、「文字エンコードをカスタマイズする」を参照してください。For information about how to override the default System.Text.Json behavior, see Customize character encoding.

コメントComments

逆シリアル化中、Newtonsoft.Json では既定で JSON 内のコメントは無視されます。During deserialization, Newtonsoft.Json ignores comments in the JSON by default. System.Text.Json の既定では、コメントに対して例外がスローされます。RFC 8259 仕様にそれが含まれていないためです。The System.Text.Json default is to throw exceptions for comments because the RFC 8259 specification doesn't include them. コメントを許可する方法については、「コメントと末尾のコンマを許可する」を参照してください。For information about how to allow comments, see Allow comments and trailing commas.

末尾のコンマTrailing commas

逆シリアル化中、Newtonsoft.Json では既定で末尾のコンマは無視されます。During deserialization, Newtonsoft.Json ignores trailing commas by default. また、複数の末尾のコンマ (たとえば、[{"Color":"Red"},{"Color":"Green"},,]) も無視されます。It also ignores multiple trailing commas (for example, [{"Color":"Red"},{"Color":"Green"},,]). System.Text.Json の既定では、末尾のコンマに対して例外がスローされます。RFC 8259 仕様でそれが許可されていないためです。The System.Text.Json default is to throw exceptions for trailing commas because the RFC 8259 specification doesn't allow them. System.Text.Json で受け入れられるようにする方法については、「コメントと末尾のコンマを許可する」を参照してください。For information about how to make System.Text.Json accept them, see Allow comments and trailing commas. 複数の末尾のコンマが許可されるようにする方法はありません。There's no way to allow multiple trailing commas.

コンバーターの登録の優先順位Converter registration precedence

Newtonsoft.Json でのカスタム コンバーターの登録の優先順位は次のとおりです。The Newtonsoft.Json registration precedence for custom converters is as follows:

  • プロパティの属性Attribute on property
  • 型の属性Attribute on type
  • Converters コレクションConverters collection

この順序は、Converters コレクション内のカスタム コンバーターが、型レベルの属性を適用して登録されたコンバーターによってオーバーライドされることを意味します。This order means that a custom converter in the Converters collection is overridden by a converter that is registered by applying an attribute at the type level. これらの登録はどちらも、プロパティ レベルの属性によってオーバーライドされます。Both of those registrations are overridden by an attribute at the property level.

System.Text.Json でのカスタム コンバーターの登録の優先順位は異なります。The System.Text.Json registration precedence for custom converters is different:

  • プロパティの属性Attribute on property
  • Converters コレクションConverters collection
  • 型の属性Attribute on type

ここでの違いは、Converters コレクション内のカスタム コンバーターによって型レベルの属性がオーバーライドされる点です。The difference here is that a custom converter in the Converters collection overrides an attribute at the type level. この優先順位の背後にある意図は、実行時の変更によって設計時の選択がオーバーライドされるようにすることです。The intention behind this order of precedence is to make run-time changes override design-time choices. 優先順位を変更する方法はありません。There's no way to change the precedence.

カスタム コンバーターの登録の詳細については、「カスタム コンバーターを登録する」を参照してください。For more information about custom converter registration, see Register a custom converter.

最大の深さMaximum depth

Newtonsoft.Json の場合、既定では最大の深さの制限はありません。Newtonsoft.Json doesn't have a maximum depth limit by default. System.Text.Json の場合、64 という既定の制限があり、JsonSerializerOptions.MaxDepth を設定して構成できます。For System.Text.Json there's a default limit of 64, and it's configurable by setting JsonSerializerOptions.MaxDepth.

ASP.NET Core を使用し、System.Text.Json を間接的に使用している場合、深さ上限の既定値は 32 です。If you're using System.Text.Json indirectly by using ASP.NET Core, the default maximum depth limit is 32. この既定値はモデル バインドの場合と同じであり、JsonOptions クラスで設定されます。The default value is the same as for model binding and is set in the JsonOptions class.

JSON 文字列 (プロパティ名と文字列値)JSON strings (property names and string values)

逆シリアル化中、Newtonsoft.Json では、二重引用符か単一引用符で囲まれた、または引用符なしのプロパティ名が受け取入れられます。During deserialization, Newtonsoft.Json accepts property names surrounded by double quotes, single quotes, or without quotes. 文字列値は、二重引用符または単一引用符で囲まれたものが受け入れられます。It accepts string values surrounded by double quotes or single quotes. たとえば、Newtonsoft.Json では次の JSON が受け入れられます。For example, Newtonsoft.Json accepts the following JSON:

{
  "name1": "value",
  'name2': "value",
  name3: 'value'
}

System.Text.Json では、二重引用符で囲まれたプロパティ名と文字列値のみが受け入れられます。この形式が RFC 8259 仕様で要求されており、有効な JSON と見なされる唯一の形式であるためです。System.Text.Json only accepts property names and string values in double quotes because that format is required by the RFC 8259 specification and is the only format considered valid JSON.

値を単一引用符で囲むと、次のメッセージと共に JsonException が発生します。A value enclosed in single quotes results in a JsonException with the following message:

''' is an invalid start of a value.

文字列プロパティに対する文字列以外の値Non-string values for string properties

Newtonsoft.Json では、文字列型のプロパティへの逆シリアル化の場合、数値やリテラル truefalse など、文字列以外の値が受け入れられます。Newtonsoft.Json accepts non-string values, such as a number or the literals true and false, for deserialization to properties of type string. Newtonsoft.Json で次のクラスへの逆シリアル化が正常に行われてる JSON の例を、以下に示します。Here's an example of JSON that Newtonsoft.Json successfully deserializes to the following class:

{
  "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 では、文字列以外の値は文字列プロパティに逆シリアル化されません。System.Text.Json doesn't deserialize non-string values into string properties. 文字列フィールドに対して文字列以外の値を受け取ると、次のメッセージと共に JsonException が発生します。A non-string value received for a string field results in a JsonException with the following message:

The JSON value could not be converted to System.String.

JsonSerializer を使用するシナリオScenarios using JsonSerializer

次のシナリオの一部は、組み込み機能ではサポートされていませんが、回避策を適用できます。Some of the following scenarios aren't supported by built-in functionality, but workarounds are possible. 回避策とはカスタム コンバーターのことですが、これによって Newtonsoft.Json の機能との完全なパリティが得られるとは限りません。The workarounds are custom converters, which may not provide complete parity with Newtonsoft.Json functionality. これらの一部については、サンプル コードが例として提供されます。For some of these, sample code is provided as examples. Newtonsoft.Json のこれらの機能を利用する必要がある場合、移行するには、.NET オブジェクト モデルに対する変更やその他のコード変更が必要になります。If you rely on these Newtonsoft.Json features, migration will require modifications to your .NET object models or other code changes.

次のシナリオの一部では、回避策は実用的でないか不可能です。For some of the following scenarios, workarounds are not practical or possible. Newtonsoft.Json のこれらの機能を利用する必要がある場合、移行を可能にするには大幅な変更が必要です。If you rely on these Newtonsoft.Json features, migration will not be possible without significant changes.

引用符で囲まれた数値を許可または記述するAllow or write numbers in quotes

Newtonsoft.Json では、JSON 文字列によって表された (引用符で囲まれた) 数値をシリアル化または逆シリアル化できます。Newtonsoft.Json can serialize or deserialize numbers represented by JSON strings (surrounded by quotes). たとえば、{"DegreesCelsius":23} ではなく {"DegreesCelsius":"23"} を受け入れることができます。For example, it can accept: {"DegreesCelsius":"23"} instead of {"DegreesCelsius":23}. System.Text.Json でその動作を有効にするには、JsonSerializerOptions.NumberHandlingWriteAsString または AllowReadingFromString に設定するか、[JsonNumberHandling] 属性を使用します。To enable that behavior in System.Text.Json, set JsonSerializerOptions.NumberHandling to WriteAsString or AllowReadingFromString, or use the [JsonNumberHandling] attribute.

ASP.NET Core を使用して System.Text.Json を間接的に使用している場合、Newtonsoft.Json のような動作を得るために何かをする必要はありません。If you're using System.Text.Json indirectly by using ASP.NET Core, you don't need to do anything to get behavior like Newtonsoft.Json. System.Text.Json が使用されていて、Web の既定値で引用符で囲まれた数値が許可されている場合、ASP.NET Core により Web の既定値が指定されます。ASP.NET Core specifies web defaults when it uses System.Text.Json, and web defaults allow quoted numbers.

詳細については、「引用符で囲まれた数値を許可または記述する」を参照してください。For more information, see Allow or write numbers in quotes.

Newtonsoft.Json では、JSON 文字列によって表された (引用符で囲まれた) 数値をシリアル化または逆シリアル化できます。Newtonsoft.Json can serialize or deserialize numbers represented by JSON strings (surrounded by quotes). たとえば、{"DegreesCelsius":23} ではなく {"DegreesCelsius":"23"} を受け入れることができます。For example, it can accept: {"DegreesCelsius":"23"} instead of {"DegreesCelsius":23}. .NET Core 3.1 の System.Text.Json でその動作を有効にするには、次の例のようなカスタム コンバーターを実装します。To enable that behavior in System.Text.Json in .NET Core 3.1, implement a custom converter like the following example. このコンバーターでは、long として定義されたプロパティが処理されます。The converter handles properties defined as long:

  • JSON 文字列としてシリアル化されます。It serializes them as JSON strings.
  • 逆シリアル化中に、JSON の数値と引用符で囲まれた数値が受け入れられます。It accepts JSON numbers and numbers within quotes while deserializing.
using System;
using System.Buffers;
using System.Buffers.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class LongToStringConverter : JsonConverter<long>
    {
        public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
                if (Utf8Parser.TryParse(span, out long number, out int bytesConsumed) && span.Length == bytesConsumed)
                    return number;

                if (Int64.TryParse(reader.GetString(), out number))
                    return number;
            }

            return reader.GetInt64();
        }

        public override void Write(Utf8JsonWriter writer, long longValue, JsonSerializerOptions options)
        {
            writer.WriteStringValue(longValue.ToString());
        }
    }
}

このカスタム コンバーターを登録するには、個々の long プロパティで属性を使用するか、Converters コレクションにコンバーター を追加します。Register this custom converter by using an attribute on individual long properties or by adding the converter to the Converters collection.

逆シリアル化のときに使用するコンストラクターを指定するSpecify constructor to use when deserializing

Newtonsoft.Json[JsonConstructor] 属性を使用すると、POCO への逆シリアル化時に呼び出すコンストラクターを指定できます。The Newtonsoft.Json [JsonConstructor] attribute lets you specify which constructor to call when deserializing to a POCO.

System.Text.Json には、[JsonConstructor] 属性もあります。System.Text.Json also has a [JsonConstructor] attribute. 詳細については、「不変の型とレコード」を参照してください。For more information, see Immutable types and Records.

.NET Core 3.1 の System.Text.Json では、パラメーターなしのコンストラクターのみがサポートされます。System.Text.Json in .NET Core 3.1 supports only parameterless constructors. 回避策として、必要なコンストラクターをカスタム コンバーターで呼び出すことができます。As a workaround, you can call whichever constructor you need in a custom converter. 不変のクラスと構造体への逆シリアル化」の例を参照してください。See the example for Deserialize to immutable classes and structs.

プロパティを条件付きで無視するConditionally ignore a property

Newtonsoft.Json には、シリアル化または逆シリアル化時にプロパティを条件付きで無視する方法がいくつか用意されています。Newtonsoft.Json has several ways to conditionally ignore a property on serialization or deserialization:

  • DefaultContractResolver を使用すると、任意の条件に基づいて含めたり無視したりするプロパティを選択できます。DefaultContractResolver lets you select properties to include or ignore, based on arbitrary criteria.
  • JsonSerializerSettingsNullValueHandlingDefaultValueHandling の設定を使用すると、null 値または既定値のすべてのプロパティを無視することを指定できます。The NullValueHandling and DefaultValueHandling settings on JsonSerializerSettings let you specify that all null-value or default-value properties should be ignored.
  • [JsonProperty] 属性の NullValueHandlingDefaultValueHandling の設定を使用すると、null または既定値に設定されている場合に無視する個々のプロパティを指定できます。The NullValueHandling and DefaultValueHandling settings on the [JsonProperty] attribute let you specify individual properties that should be ignored when set to null or the default value.

System.Text.Json には、シリアル化中にプロパティまたはフィールドを無視するために次の方法が用意されています。System.Text.Json provides the following ways to ignore properties or fields while serializing:

.NET Core 3.1 の System.Text.Json には、シリアル化中にプロパティを無視するために次の方法が用意されています。System.Text.Json in .NET Core 3.1 provides the following ways to ignore properties while serializing:

  • プロパティで [JsonIgnore] 属性を使用すると、シリアル化中にそのプロパティが JSON から除外されます。The [JsonIgnore] attribute on a property causes the property to be omitted from the JSON during serialization.
  • IgnoreNullValues グローバル オプションを使用すると、すべての null 値プロパティを無視できます。The IgnoreNullValues global option lets you ignore all null-value properties.
  • IgnoreReadOnlyProperties グローバル オプションを使用すると、すべての読み取り専用プロパティを無視できます。The IgnoreReadOnlyProperties global option lets you ignore all read-only properties.

これらのオプションでは、以下を行うことは できませんThese options don't let you:

  • 実行時に評価される任意の基準に基づいて、選択したプロパティを無視する。Ignore selected properties based on arbitrary criteria evaluated at run time.
  • 型に対して既定値を持つすべてのプロパティを無視する。Ignore all properties that have the default value for the type.
  • 型に対して既定値を持つ、選択したプロパティを無視する。Ignore selected properties that have the default value for the type.
  • 選択したプロパティを、値が null である場合に無視する。Ignore selected properties if their value is null.
  • 実行時に評価される任意の基準に基づいて、選択したプロパティを無視する。Ignore selected properties based on arbitrary criteria evaluated at run time.

この機能のために、カスタム コンバーターを記述できます。For that functionality, you can write a custom converter. この方法を紹介するサンプルの POCO とそれに対するカスタム コンバーターを、次に示します。Here's a sample POCO and a custom converter for it that illustrates this approach:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class WeatherForecastRuntimeIgnoreConverter : JsonConverter<WeatherForecast>
    {
        public override WeatherForecast Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException();
            }

            var wf = new WeatherForecast();

            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    return wf;
                }

                if (reader.TokenType == JsonTokenType.PropertyName)
                {
                    string propertyName = reader.GetString();
                    reader.Read();
                    switch (propertyName)
                    {
                        case "Date":
                            DateTimeOffset date = reader.GetDateTimeOffset();
                            wf.Date = date;
                            break;
                        case "TemperatureCelsius":
                            int temperatureCelsius = reader.GetInt32();
                            wf.TemperatureCelsius = temperatureCelsius;
                            break;
                        case "Summary":
                            string summary = reader.GetString();
                            wf.Summary = string.IsNullOrWhiteSpace(summary) ? "N/A" : summary;
                            break;
                    }
                }
            }

            throw new JsonException();
        }

        public override void Write(Utf8JsonWriter writer, WeatherForecast wf, JsonSerializerOptions options)
        {
            writer.WriteStartObject();

            writer.WriteString("Date", wf.Date);
            writer.WriteNumber("TemperatureCelsius", wf.TemperatureCelsius);
            if (!string.IsNullOrWhiteSpace(wf.Summary) && wf.Summary != "N/A")
            {
                writer.WriteString("Summary", wf.Summary);
            }

            writer.WriteEndObject();
        }
    }
}

このコンバーターでは、Summary プロパティは、値が null、空の文字列、または "N/A" の場合、シリアル化から除外されます。The converter causes the Summary property to be omitted from serialization if its value is null, an empty string, or "N/A".

このカスタム コンバーターを登録するには、クラスで属性を使用するか、Converters コレクションにコンバーター を追加します。Register this custom converter by using an attribute on the class or by adding the converter to the Converters collection.

この方法では、次の場合に追加のロジックが必要になります。This approach requires additional logic if:

  • POCO に複合プロパティが含まれている。The POCO includes complex properties.
  • [JsonIgnore] などの属性や、カスタム エンコーダーなどのオプションを処理する必要がある。You need to handle attributes such as [JsonIgnore] or options such as custom encoders.

パブリックおよび非パブリック フィールドPublic and non-public fields

Newtonsoft.Json では、フィールドおよびプロパティをシリアル化および逆シリアル化できます。Newtonsoft.Json can serialize and deserialize fields as well as properties.

System.Text.Json では、シリアル化または逆シリアル化のときにフィールドを含めるには、JsonSerializerOptions.IncludeFields グローバル設定または [JsonInclude] 属性を使用します。In System.Text.Json, use the JsonSerializerOptions.IncludeFields global setting or the [JsonInclude] attribute to include public fields when serializing or deserializing. 例については、「フィールドを含める」を参照してください。For an example, see Include fields.

.NET Core 3.1 の System.Text.Json は、パブリック プロパティでのみ機能します。System.Text.Json in .NET Core 3.1 only works with public properties. この機能は、カスタム コンバーターによって得られます。Custom converters can provide this functionality.

オブジェクト参照を保持してループを処理するPreserve object references and handle loops

既定では、Newtonsoft.Json では値によってシリアル化します。By default, Newtonsoft.Json serializes by value. たとえば、オブジェクトに同じ Person オブジェクトへの参照を含む 2 つのプロパティが含まれている場合、その Person オブジェクトのプロパティの値は JSON 内で複製されます。For example, if an object contains two properties that contain a reference to the same Person object, the values of that Person object's properties are duplicated in the JSON.

Newtonsoft.Json には、JsonSerializerSettings に、参照によってシリアル化できるようにする PreserveReferencesHandling 設定があります。Newtonsoft.Json has a PreserveReferencesHandling setting on JsonSerializerSettings that lets you serialize by reference:

  • 最初の Person オブジェクト用に作成された JSON に識別子メタデータが追加されます。An identifier metadata is added to the JSON created for the first Person object.
  • 2番目の Person オブジェクト用に作成された JSON には、プロパティ値ではなく、その識別子への参照が含まれます。The JSON that is created for the second Person object contains a reference to that identifier instead of property values.

Newtonsoft.Json には、例外をスローするのではなく循環参照を無視できるようにする ReferenceLoopHandling 設定もあります。Newtonsoft.Json also has a ReferenceLoopHandling setting that lets you ignore circular references rather than throw an exception.

System.Text.Json で参照を保持し、循環参照を処理するには、JsonSerializerOptions.ReferenceHandlerPreserve に設定します。To preserve references and handle circular references in System.Text.Json, set JsonSerializerOptions.ReferenceHandler to Preserve. ReferenceHandler.Preserve 設定は、Newtonsoft.Json での PreserveReferencesHandling = PreserveReferencesHandling.All に相当します。The ReferenceHandler.Preserve setting is equivalent to PreserveReferencesHandling = PreserveReferencesHandling.All in Newtonsoft.Json.

Newtonsoft.Json の ReferenceResolver のように、シリアル化および逆シリアル化で参照を維持するための動作は、System.Text.Json.Serialization.ReferenceResolver クラスによって定義されます。Like the Newtonsoft.Json ReferenceResolver, the System.Text.Json.Serialization.ReferenceResolver class defines the behavior of preserving references on serialization and deserialization. カスタム動作を指定するには、派生クラスを作成します。Create a derived class to specify custom behavior. 例については、GuidReferenceResolver に関するページを参照してください。For an example, see GuidReferenceResolver.

一部の関連する Newtonsoft.Json 機能はサポートされていません。Some related Newtonsoft.Json features are not supported:

詳細については、「参照を保持し、循環参照を処理する」を参照してくださいFor more information, see Preserve references and handle circular references

.NET Core 3.1 の System.Text.Json でサポートされているのは値によるシリアル化のみであり、循環参照の場合は例外がスローされます。System.Text.Json in .NET Core 3.1 only supports serialization by value and throws an exception for circular references.

文字列以外のキーを含むディクショナリDictionary with non-string key

Newtonsoft.JsonSystem.Text.Json のどちらでも、Dictionary<TKey, TValue> 型のコレクションがサポートされています。Both Newtonsoft.Json and System.Text.Json support collections of type Dictionary<TKey, TValue>.

Newtonsoft.Json では、Dictionary<TKey, TValue> 型のコレクションがサポートされます。Newtonsoft.Json supports collections of type Dictionary<TKey, TValue>. .NET Core 3.1 の System.Text.Json では、ディクショナリ コレクションに対する組み込みサポートは Dictionary<string, TValue> に限定されています。The built-in support for dictionary collections in System.Text.Json in .NET Core 3.1 is limited to Dictionary<string, TValue>. つまり、キーは文字列である必要があります。That is, the key must be a string.

.NET Core 3.1 でキーとして整数やその他の型を含むディクショナリをサポートするには、「カスタム コンバーターを記述する方法」の例にあるようなコンバーターを作成します。To support a dictionary with an integer or some other type as the key in .NET Core 3.1, create a converter like the example in How to write custom converters.

組み込みサポートのない型Types without built-in support

System.Text.Json には、次の型に対する組み込みサポートはありません。System.Text.Json doesn't provide built-in support for the following types:

カスタム コンバーターは、組み込みサポートのない型に対して実装できます。Custom converters can be implemented for types that don't have built-in support.

ポリモーフィックなシリアル化Polymorphic serialization

Newtonsoft.Json では、ポリモーフィックなシリアル化が自動的に行われます。Newtonsoft.Json automatically does polymorphic serialization. System.Text.Json の制限付きのポリモーフィックなシリアル化機能については、「派生クラスのプロパティのシリアル化」を参照してください。For information about the limited polymorphic serialization capabilities of System.Text.Json, see Serialize properties of derived classes.

そこで説明されている回避策は、派生クラスを含むことができるプロパティを、object 型として定義することです。The workaround described there is to define properties that may contain derived classes as type object. これが不可能な場合、別のオプションとして、カスタム コンバーターを記述する方法に関する記事の例にあるような、継承型階層全体に対する Write メソッドを使用してコンバーターを作成する方法があります。If that isn't possible, another option is to create a converter with a Write method for the whole inheritance type hierarchy like the example in How to write custom converters.

ポリモーフィックな逆シリアル化Polymorphic deserialization

Newtonsoft.Json には、シリアル化中に型名のメタデータを JSON に追加する TypeNameHandling 設定があります。Newtonsoft.Json has a TypeNameHandling setting that adds type name metadata to the JSON while serializing. これは、逆シリアル化中にそのメタデータを使用して、ポリモーフィックな逆シリアル化を行います。It uses the metadata while deserializing to do polymorphic deserialization. System.Text.Json では限定された範囲のポリモーフィックなシリアル化を行うことができますが、ポリモーフィックな逆シリアル化を行うことはできません。System.Text.Json can do a limited range of polymorphic serialization but not polymorphic deserialization.

ポリモーフィックな逆シリアル化をサポートするには、カスタム コンバーターを記述する方法に関する記事の例にあるようなコンバーターを作成します。To support polymorphic deserialization, create a converter like the example in How to write custom converters.

オブジェクト プロパティの逆シリアル化Deserialization of object properties

Newtonsoft.Json では、Object への逆シリアル化中に以下が行われます。When Newtonsoft.Json deserializes to Object, it:

  • JSON ペイロード内のプリミティブ値 (null 以外) の型を推測し、格納されている stringlongdoubleboolean、または DateTime をボックス化されたオブジェクトとして返します。Infers the type of primitive values in the JSON payload (other than null) and returns the stored string, long, double, boolean, or DateTime as a boxed object. " プリミティブ値 " は、JSON の数値、文字列、truefalsenull などの 1 つの JSON 値です。Primitive values are single JSON values such as a JSON number, string, true, false, or null.
  • JSON ペイロード内の複合値の JObject または JArray を返します。Returns a JObject or JArray for complex values in the JSON payload. " 複合値 " は、中かっこ ({}) 内の JSON のキーと値のペアのコレクション、または角かっこ ([]) 内の値のリストです。Complex values are collections of JSON key-value pairs within braces ({}) or lists of values within brackets ([]). 中かっこまたは角かっこ内のプロパティと値には、追加のプロパティまたは値を含めることができます。The properties and values within the braces or brackets can have additional properties or values.
  • ペイロードに null JSON リテラルが含まれている場合は、null 参照を返します。Returns a null reference when the payload has the null JSON literal.

System.Text.Json では、Object への逆シリアル化中には常に、プリミティブと複合の両方の値に対してボックス化された JsonElement が格納されます。例えば、以下のようなものです。System.Text.Json stores a boxed JsonElement for both primitive and complex values whenever deserializing to Object, for example:

  • object プロパティ。An object property.
  • object ディクショナリ値。An object dictionary value.
  • object 配列値。An object array value.
  • ルート objectA root object.

ただし、System.Text.Json では nullNewtonsoft.Json と同じ方法で処理され、ペイロードに null JSON リテラルが含まれている場合は null 参照が返されます。However, System.Text.Json treats null the same as Newtonsoft.Json and returns a null reference when the payload has the null JSON literal in it.

object プロパティに型の推定を実装するには、カスタム コンバーターを記述する方法に関する記事の例にあるようなコンバーターを作成します。To implement type inference for object properties, create a converter like the example in How to write custom converters.

null を null 非許容型に逆シリアル化するDeserialize null to non-nullable type

Newtonsoft.Json では、次のシナリオでは例外がスローされません。Newtonsoft.Json doesn't throw an exception in the following scenario:

  • NullValueHandlingIgnore に設定されている。さらにNullValueHandling is set to Ignore, and
  • 逆シリアル化中に、JSON の null 非許容値型に null 値が含まれている。During deserialization, the JSON contains a null value for a non-nullable value type.

System.Text.Json では、同じシナリオで例外がスローされます。In the same scenario, System.Text.Json does throw an exception. (System.Text.Json での対応する null 処理設定は JsonSerializerOptions.IgnoreNullValues = true です。)(The corresponding null-handling setting in System.Text.Json is JsonSerializerOptions.IgnoreNullValues = true.)

ターゲット型を所有している場合、最適な回避策は、問題のプロパティを null 許容にすることです (たとえば、intint? に変更します)。If you own the target type, the best workaround is to make the property in question nullable (for example, change int to int?).

もう 1 つの回避策として、DateTimeOffset 型に対する null 値を処理する次の例のように、型のコンバーターを作成する方法があります。Another workaround is to make a converter for the type, such as the following example that handles null values for DateTimeOffset types:

using System;
using System.Globalization;
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)
        {
            if (reader.TokenType == JsonTokenType.Null)
            {
                return default;
            }
            return reader.GetDateTimeOffset();
        }

        public override void Write(
            Utf8JsonWriter writer,
            DateTimeOffset dateTimeValue,
            JsonSerializerOptions options)
        {
            writer.WriteStringValue(dateTimeValue);
        }
    }
}

このカスタム コンバーターを登録するには、プロパティで属性を使用するか、Converters コレクションにコンバーター を追加します。Register this custom converter by using an attribute on the property or by adding the converter to the Converters collection.

注: 上記のコンバーターでは、既定値を指定する POCO に対して Newtonsoft.Json が処理する場合とは 異なる方法で null 値が処理 されます。Note: The preceding converter handles null values differently than Newtonsoft.Json does for POCOs that specify default values. たとえば、次のコードがターゲット オブジェクトを表しているとします。For example, suppose the following code represents your target object:

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 が逆シリアル化されるとします。And suppose the following JSON is deserialized by using the preceding converter:

{
  "Date": null,
  "TemperatureCelsius": 25,
  "Summary": null
}

逆シリアル化が行われた後、Date プロパティには 1/1/0001 (default(DateTimeOffset)) が設定されます。つまり、コンストラクターで設定された値が上書きされます。After deserialization, the Date property has 1/1/0001 (default(DateTimeOffset)), that is, the value set in the constructor is overwritten. 同じ POCO と JSON を使用する場合、Newtonsoft.Json の逆シリアル化では Date プロパティに 1/1/2001 が設定されたままになります。Given the same POCO and JSON, Newtonsoft.Json deserialization would leave 1/1/2001 in the Date property.

不変のクラスと構造体への逆シリアル化Deserialize to immutable classes and structs

Newtonsoft.Json では、パラメーターを持つコンストラクターを使用できるため、不変のクラスと構造体に逆シリアル化できます。Newtonsoft.Json can deserialize to immutable classes and structs because it can use constructors that have parameters.

System.Text.Json では、パラメーター化されたコンストラクターの使用を指定するには [JsonConstructor] 属性を使用します。In System.Text.Json, use the [JsonConstructor] attribute to specify use of a parameterized constructor. C# 9 のレコードも不変であり、逆シリアル化ターゲットとしてサポートされています。Records in C# 9 are also immutable and are supported as deserialization targets. 詳細については、「不変の型とレコード」を参照してください。For more information, see Immutable types and Records.

.NET Core 3.1 の System.Text.Json では、パラメーターなしのパブリック コンストラクターのみがサポートされます。System.Text.Json in .NET Core 3.1 supports only public parameterless constructors. 回避策として、カスタム コンバーターでパラメーターを持つコンストラクターを呼び出すことができます。As a workaround, you can call a constructor with parameters in a custom converter.

複数のコンストラクター パラメーターを持つ不変の構造体を次に示します。Here's an immutable struct with multiple constructor parameters:

public readonly struct ImmutablePoint
{
    public ImmutablePoint(int x, int y)
    {
        X = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}

さらに、この構造体をシリアル化および逆シリアル化するコンバーターを示します。And here's a converter that serializes and deserializes this struct:

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

namespace SystemTextJsonSamples
{
    public class ImmutablePointConverter : JsonConverter<ImmutablePoint>
    {
        private readonly JsonEncodedText XName = JsonEncodedText.Encode("X");
        private readonly JsonEncodedText YName = JsonEncodedText.Encode("Y");

        private readonly JsonConverter<int> _intConverter;

        public ImmutablePointConverter(JsonSerializerOptions options)
        {
            if (options?.GetConverter(typeof(int)) is JsonConverter<int> intConverter)
            {
                _intConverter = intConverter;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }

        public override ImmutablePoint Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException();
            };

            int x = default;
            bool xSet = false;

            int y = default;
            bool ySet = false;

            // Get the first property.
            reader.Read();
            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException();
            }

            if (reader.ValueTextEquals(XName.EncodedUtf8Bytes))
            {
                x = ReadProperty(ref reader, options);
                xSet = true;
            }
            else if (reader.ValueTextEquals(YName.EncodedUtf8Bytes))
            {
                y = ReadProperty(ref reader, options);
                ySet = true;
            }
            else
            {
                throw new JsonException();
            }

            // Get the second property.
            reader.Read();
            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException();
            }

            if (xSet && reader.ValueTextEquals(YName.EncodedUtf8Bytes))
            {
                y = ReadProperty(ref reader, options);
            }
            else if (ySet && reader.ValueTextEquals(XName.EncodedUtf8Bytes))
            {
                x = ReadProperty(ref reader, options);
            }
            else
            {
                throw new JsonException();
            }

            reader.Read();

            if (reader.TokenType != JsonTokenType.EndObject)
            {
                throw new JsonException();
            }

            return new ImmutablePoint(x, y);
        }

        private int ReadProperty(ref Utf8JsonReader reader, JsonSerializerOptions options)
        {
            Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);

            reader.Read();
            return _intConverter.Read(ref reader, typeof(int), options);
        }

        private void WriteProperty(Utf8JsonWriter writer, JsonEncodedText name, int intValue, JsonSerializerOptions options)
        {
            writer.WritePropertyName(name);
            _intConverter.Write(writer, intValue, options);
        }

        public override void Write(
            Utf8JsonWriter writer,
            ImmutablePoint point,
            JsonSerializerOptions options)
        {
            writer.WriteStartObject();
            WriteProperty(writer, XName, point.X, options);
            WriteProperty(writer, YName, point.Y, options);
            writer.WriteEndObject();
        }
    }
}

このカスタム コンバーターを登録するには、Converters コレクションにコンバーターを追加します。Register this custom converter by adding the converter to the Converters collection.

オープン ジェネリック プロパティを処理する同様のコンバーターの例については、キーと値のペアの組み込みコンバーターに関する記事を参照してください。For an example of a similar converter that handles open generic properties, see the built-in converter for key-value pairs.

必須プロパティRequired properties

Newtonsoft.Json では、[JsonProperty] 属性に Required を設定して、プロパティが必須であることを指定します。In Newtonsoft.Json, you specify that a property is required by setting Required on the [JsonProperty] attribute. 必須とマーク付けされたプロパティに対して JSON で値が取得されない場合、Newtonsoft.Json で例外がスローされます。Newtonsoft.Json throws an exception if no value is received in the JSON for a property marked as required.

System.Text.Json では、ターゲット型のいずれかのプロパティに対して値が取得されない場合でも、例外はスローされません。System.Text.Json doesn't throw an exception if no value is received for one of the properties of the target type. たとえば、WeatherForecast クラスがあるとします。For example, if you have a WeatherForecast class:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}

次の JSON はエラーなしで逆シリアル化されます。The following JSON is deserialized without error:

{
    "TemperatureCelsius": 25,
    "Summary": "Hot"
}

JSON に Date プロパティがない場合に逆シリアル化が失敗するようにするには、カスタム コンバーターを実装します。To make deserialization fail if no Date property is in the JSON, implement a custom converter. 次のサンプル コンバーター コードでは、逆シリアル化の完了後に Date プロパティが設定されていない場合は例外がスローされます。The following sample converter code throws an exception if the Date property isn't set after deserialization is complete:

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

namespace SystemTextJsonSamples
{
    public class WeatherForecastRequiredPropertyConverter : JsonConverter<WeatherForecast>
    {
        public override WeatherForecast Read(
            ref Utf8JsonReader reader,
            Type type,
            JsonSerializerOptions options)
        {
            // Don't pass in options when recursively calling Deserialize.
            WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader);

            // Check for required fields set by values in JSON
            if (forecast.Date == default)
            {
                throw new JsonException("Required property not received in the JSON");
            }
            return forecast;
        }

        public override void Write(
            Utf8JsonWriter writer,
            WeatherForecast forecast, JsonSerializerOptions options)
        {
            // Don't pass in options when recursively calling Serialize.
            JsonSerializer.Serialize(writer, forecast);
        }
    }
}

このカスタム コンバーターを登録するには、JsonSerializerOptions.Converters コレクションにコンバーターを追加します。Register this custom converter by adding the converter to the JsonSerializerOptions.Converters collection.

コンバーターを再帰的に呼び出すこのパターンでは、属性を使用するのではなく、JsonSerializerOptions を使用してコンバーターを登録する必要があります。This pattern of recursively calling the converter requires that you register the converter by using JsonSerializerOptions, not by using an attribute. 属性を使用してこのコンバーターを登録する場合、カスタム コンバーターによってそれ自体が再帰的に呼び出されます。If you register the converter by using an attribute, the custom converter recursively calls into itself. その結果、スタック オーバーフロー例外で終了する無限ループが発生します。The result is an infinite loop that ends in a stack overflow exception.

オプション オブジェクトを使用してコンバーターを登録する場合は、Serialize または Deserialize を再帰的に呼び出すときにオプション オブジェクトで渡さないようにして、無限ループを回避します。When you register the converter by using the options object, avoid an infinite loop by not passing in the options object when recursively calling Serialize or Deserialize. オプション オブジェクトには、Converters コレクションが含まれています。The options object contains the Converters collection. それを Serialize または Deserialize に渡すと、カスタム コンバーターはそれ自体を呼び出し、無限ループが形成され、結果的にスタック オーバーフロー例外が発生します。If you pass it in to Serialize or Deserialize, the custom converter calls into itself, making an infinite loop that results in a stack overflow exception. 既定のオプションを使用できない場合は、必要な設定を使用してオプションの新しいインスタンスを作成します。If the default options are not feasible, create a new instance of the options with the settings that you need. この方法では、新しい各インスタンスが個別にキャッシュされるため、速度が遅くなります。This approach will be slow since each new instance caches independently.

変換されるクラスで JsonConverterAttribute の登録を使用できる代替パターンがあります。There is an alternative pattern that can use JsonConverterAttribute registration on the class to be converted. この方法では、変換されるクラスから派生したクラスで、コンバーター コードによって Serialize または Deserialize が呼び出されます。In this approach, the converter code calls Serialize or Deserialize on a class that derives from the class to be converted. この派生クラスには、JsonConverterAttribute が適用されていません。The derived class doesn't have a JsonConverterAttribute applied to it. この代替の例を次に示します。In the following example of this alternative:

  • WeatherForecastWithRequiredPropertyConverterAttribute は、逆シリアル化されるクラスであり、JsonConverterAttribute が適用されています。WeatherForecastWithRequiredPropertyConverterAttribute is the class to be deserialized and has the JsonConverterAttribute applied to it.
  • WeatherForecastWithoutRequiredPropertyConverterAttribute は、コンバーター属性を持たない派生クラスです。WeatherForecastWithoutRequiredPropertyConverterAttribute is the derived class that doesn't have the converter attribute.
  • 無限ループを回避するために、コンバーターのコードによって、WeatherForecastWithoutRequiredPropertyConverterAttributeSerializeDeserialize が呼び出されます。The code in the converter calls Serializeand Deserialize on WeatherForecastWithoutRequiredPropertyConverterAttribute to avoid an infinite loop. 追加のオブジェクトのインスタンス化とプロパティ値のコピーによって、このシリアル化の方法にはパフォーマンス コストが発生します。There is a performance cost to this approach on serialization due to an extra object instantiation and copying of property values.

次に WeatherForecast* の種類を示します。Here are the WeatherForecast* types:

[JsonConverter(typeof(WeatherForecastRequiredPropertyConverterForAttributeRegistration))]
public class WeatherForecastWithRequiredPropertyConverterAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}

public class WeatherForecastWithoutRequiredPropertyConverterAttribute : WeatherForecastWithRequiredPropertyConverterAttribute
{
}

コンバーターを次に示します。And here is the converter:

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

namespace SystemTextJsonSamples
{
    public class WeatherForecastRequiredPropertyConverterForAttributeRegistration : 
        JsonConverter<WeatherForecastWithRequiredPropertyConverterAttribute>
    {
        public override WeatherForecastWithRequiredPropertyConverterAttribute Read(
            ref Utf8JsonReader reader,
            Type type,
            JsonSerializerOptions options)
        {
            // OK to pass in options when recursively calling Deserialize.
            WeatherForecastWithRequiredPropertyConverterAttribute forecast = 
                JsonSerializer.Deserialize<WeatherForecastWithoutRequiredPropertyConverterAttribute>(
                    ref reader, 
                    options);

            // Check for required fields set by values in JSON.
            if (forecast.Date == default)
            {
                throw new JsonException("Required property not received in the JSON");
            }

            return forecast;
        }

        public override void Write(
            Utf8JsonWriter writer,
            WeatherForecastWithRequiredPropertyConverterAttribute forecast, 
            JsonSerializerOptions options)
        {
            var weatherForecastWithoutConverterAttributeOnClass = 
                new WeatherForecastWithoutRequiredPropertyConverterAttribute
            {
                Date = forecast.Date,
                TemperatureCelsius = forecast.TemperatureCelsius,
                Summary = forecast.Summary
            };

            // OK to pass in options when recursively calling Serialize.
            JsonSerializer.Serialize(
                writer, 
                weatherForecastWithoutConverterAttributeOnClass, 
                options);
        }
    }
}

属性 ([JsonIgnore] など) または別のオプション (カスタム エンコーダーなど) を処理する必要がある場合、必須プロパティのコンバーターには追加のロジックが必要です。The required properties converter would require additional logic if you need to handle attributes such as [JsonIgnore] or different options, such as custom encoders. また、例のコードでは、既定値がコンストラクター内で設定されているプロパティは処理されません。Also, the example code doesn't handle properties for which a default value is set in the constructor. さらに、この方法では次のシナリオの違いは識別されません。And this approach doesn't differentiate between the following scenarios:

  • プロパティが JSON から欠落している。A property is missing from the JSON.
  • null 非許容型のプロパティが JSON に存在するが、値がその型の既定である (たとえば、int ではゼロ)。A property for a non-nullable type is present in the JSON, but the value is the default for the type, such as zero for an int.
  • null 許容値型のプロパティが JSON に存在するが、値が null である。A property for a nullable value type is present in the JSON, but the value is null.

日付形式を指定するSpecify date format

Newtonsoft.Json には、DateTime および DateTimeOffset 型のプロパティをどのようにシリアル化および逆シリアル化するかを制御する方法がいくつか用意されています。Newtonsoft.Json provides several ways to control how properties of DateTime and DateTimeOffset types are serialized and deserialized:

  • DateTimeZoneHandling 設定を使用すると、すべての DateTime 値を UTC 日付としてシリアル化できます。The DateTimeZoneHandling setting can be used to serialize all DateTime values as UTC dates.
  • DateFormatString 設定と DateTime コンバーターを使用すると、日付文字列の形式をカスタマイズできます。The DateFormatString setting and DateTime converters can be used to customize the format of date strings.

System.Text.Json では、サポートが組み込まれている形式は ISO 8601-1:2019 のみです。これが広く採用されていて明確であり、ラウンド トリップが正確に行われるためです。In System.Text.Json, the only format that has built-in support is ISO 8601-1:2019 since it's widely adopted, unambiguous, and makes round trips precisely. 他の形式を使用するには、カスタム コンバーターを作成します。To use any other format, create a custom converter. 詳細については、「System.Text.Json での DateTime と DateTimeOffset のサポート」を参照してください。For more information, see DateTime and DateTimeOffset support in System.Text.Json.

コールバックCallbacks

Newtonsoft.Json では、シリアル化または逆シリアル化プロセスの複数の時点でカスタム コードを実行できます。Newtonsoft.Json lets you execute custom code at several points in the serialization or deserialization process:

  • OnDeserializing (オブジェクトの逆シリアル化の開始時点)OnDeserializing (when beginning to deserialize an object)
  • OnDeserialized (オブジェクトの逆シリアル化の完了時点)OnDeserialized (when finished deserializing an object)
  • OnSerializing (オブジェクトのシリアル化の開始時点)OnSerializing (when beginning to serialize an object)
  • OnSerialized (オブジェクトのシリアル化の完了時点)OnSerialized (when finished serializing an object)

System.Text.Json では、カスタム コンバーターを記述することでコールバックをシミュレートできます。In System.Text.Json, you can simulate callbacks by writing a custom converter. 次の例は、POCO のカスタム コンバーターを示しています。The following example shows a custom converter for a POCO. このコンバーターには、Newtonsoft.Json のコールバックに対応する各時点でメッセージを表示するコードが含まれています。The converter includes code that displays a message at each point that corresponds to a Newtonsoft.Json callback.

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

namespace SystemTextJsonSamples
{
    public class WeatherForecastCallbacksConverter : JsonConverter<WeatherForecast>
    {
        public override WeatherForecast Read(
            ref Utf8JsonReader reader,
            Type type,
            JsonSerializerOptions options)
        {
            // Place "before" code here (OnDeserializing),
            // but note that there is no access here to the POCO instance.
            Console.WriteLine("OnDeserializing");

            // Don't pass in options when recursively calling Deserialize.
            WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader);

            // Place "after" code here (OnDeserialized)
            Console.WriteLine("OnDeserialized");

            return forecast;
        }

        public override void Write(
            Utf8JsonWriter writer,
            WeatherForecast forecast, JsonSerializerOptions options)
        {
            // Place "before" code here (OnSerializing)
            Console.WriteLine("OnSerializing");

            // Don't pass in options when recursively calling Serialize.
            JsonSerializer.Serialize(writer, forecast);

            // Place "after" code here (OnSerialized)
            Console.WriteLine("OnSerialized");
        }
    }
}

このカスタム コンバーターを登録するには、Converters コレクションにコンバーターを追加します。Register this custom converter by adding the converter to the Converters collection.

上記のサンプルに従ったカスタム コンバーターを使用すると、次のようになります。If you use a custom converter that follows the preceding sample:

  • OnDeserializing コードでは、新しい POCO インスタンスにアクセスできません。The OnDeserializing code doesn't have access to the new POCO instance. 逆シリアル化の開始時に新しい POCO インスタンスを操作するには、そのコードを POCO コンストラクターに挿入します。To manipulate the new POCO instance at the start of deserialization, put that code in the POCO constructor.
  • オプション オブジェクトでコンバーターを登録し、Serialize または Deserialize を再帰的に呼び出すときにオプション オブジェクトで渡さないようにして、無限ループを回避します。Avoid an infinite loop by registering the converter in the options object and not passing in the options object when recursively calling Serialize or Deserialize.

Serialize または Deserialize を再帰的に呼び出すカスタム コンバーターの詳細については、この記事の前半にある「必須プロパティ」セクションをご覧ください。For more information about custom converters that recursively call Serialize or Deserialize, see the Required properties section earlier in this article.

非パブリック プロパティのセッターとゲッターNon-public property setters and getters

Newtonsoft.Json では、JsonProperty 属性を通じて、プライベートおよび内部プロパティのセッターとゲッターを使用できます。Newtonsoft.Json can use private and internal property setters and getters via the JsonProperty attribute.

System.Text.Json では、[JsonInclude] 属性を通じて、プライベートおよび内部プロパティのセッターとゲッターがサポートされます。System.Text.Json supports private and internal property setters and getters via the [JsonInclude] attribute. サンプル コードについては、「パブリックでないプロパティ アクセサー」を参照してください。For sample code, see Non-public property accessors.

.NET Core 3.1 の System.Text.Json では、パブリック セッターのみがサポートされています。System.Text.Json in .NET Core 3.1 supports only public setters. この機能は、カスタム コンバーターによって得られます。Custom converters can provide this functionality.

既存のオブジェクトの設定Populate existing objects

Newtonsoft.JsonJsonConvert.PopulateObject メソッドでは、新しいインスタンスを作成するのではなく、クラスの既存のインスタンスに JSON ドキュメントが逆シリアル化されます。The JsonConvert.PopulateObject method in Newtonsoft.Json deserializes a JSON document to an existing instance of a class, instead of creating a new instance. System.Text.Json では常に、既定のパラメーターなしのパブリック コンストラクターを使用して、ターゲット型の新しいインスタンスが作成されます。System.Text.Json always creates a new instance of the target type by using the default public parameterless constructor. カスタム コンバーターによって、既存のインスタンスに逆シリアル化できます。Custom converters can deserialize to an existing instance.

プロパティを置き換えるのではなく再利用するReuse rather than replace properties

Newtonsoft.JsonObjectCreationHandling 設定を使用すると、逆シリアル化中に、プロパティ内のオブジェクトを置き換えるのではなく再利用することを指定できます。The Newtonsoft.Json ObjectCreationHandling setting lets you specify that objects in properties should be reused rather than replaced during deserialization. System.Text.Json では常に、プロパティ内のオブジェクトが置き換えられます。System.Text.Json always replaces objects in properties. この機能は、カスタム コンバーターによって得られます。Custom converters can provide this functionality.

セッターなしでコレクションに追加するAdd to collections without setters

逆シリアル化中、Newtonsoft.Json ではプロパティにセッターがない場合でも、オブジェクトがコレクションに追加されます。During deserialization, Newtonsoft.Json adds objects to a collection even if the property has no setter. System.Text.Json では、セッターのないプロパティは無視されます。System.Text.Json ignores properties that don't have setters. この機能は、カスタム コンバーターによって得られます。Custom converters can provide this functionality.

System.Runtime.Serialization 属性System.Runtime.Serialization attributes

System.Text.Json では、DataMemberAttributeIgnoreDataMemberAttribute などの、System.Runtime.Serialization 名前空間の属性はサポートされません。System.Text.Json doesn't support attributes from the System.Runtime.Serialization namespace, such as DataMemberAttribute and IgnoreDataMemberAttribute.

8 進数Octal numbers

Newtonsoft.Json では、先頭にゼロを持つ数値は 8 進数として扱われます。Newtonsoft.Json treats numbers with a leading zero as octal numbers. System.Text.Json では先頭のゼロは許容されません。RFC 8259 仕様で許可されていないためです。System.Text.Json doesn't allow leading zeroes because the RFC 8259 specification doesn't allow them.

MissingMemberHandlingMissingMemberHandling

Newtonsoft.Json は、ターゲット型に存在しないプロパティが JSON に含まれている場合、逆シリアル化中に例外をスローするように構成できます。Newtonsoft.Json can be configured to throw exceptions during deserialization if the JSON includes properties that are missing in the target type. System.Text.Json では、[JsonExtensionData] 属性を使用する場合を除き、JSON 内の余分なプロパティは無視されます。System.Text.Json ignores extra properties in the JSON, except when you use the [JsonExtensionData] attribute. 欠落しているメンバー機能に対する回避策はありません。There's no workaround for the missing member feature.

TraceWriterTraceWriter

Newtonsoft.Json では、TraceWriter を使用してシリアル化または逆シリアル化によって生成されたログを表示し、デバッグできます。Newtonsoft.Json lets you debug by using a TraceWriter to view logs that are generated by serialization or deserialization. System.Text.Json では、ログ記録は行われません。System.Text.Json doesn't do logging.

JToken (JObject、JArray など) と比較した JsonDocument と JsonElementJsonDocument and JsonElement compared to JToken (like JObject, JArray)

System.Text.Json.JsonDocument には、既存の JSON ペイロードから 読み取り専用 のドキュメント オブジェクト モデル (DOM) を解析して作成する機能が用意されています。System.Text.Json.JsonDocument provides the ability to parse and build a read-only Document Object Model (DOM) from existing JSON payloads. DOM では、JSON ペイロード内のデータへのランダム アクセスが提供されます。The DOM provides random access to data in a JSON payload. ペイロードを構成する JSON 要素には、JsonElement 型を使用してアクセスできます。The JSON elements that compose the payload can be accessed via the JsonElement type. JsonElement 型には、JSON テキストを一般的な .NET 型に変換するための API が用意されています。The JsonElement type provides APIs to convert JSON text to common .NET types. JsonDocument では RootElement プロパティが公開されます。JsonDocument exposes a RootElement property.

JsonDocument は IDisposableJsonDocument is IDisposable

JsonDocument では、データのメモリ内ビューがプールされたバッファー内に作成されます。JsonDocument builds an in-memory view of the data into a pooled buffer. そのため、Newtonsoft.JsonJObjectJArray とは異なり、JsonDocument 型は IDisposable を実装し、Using ブロック内で使用される必要があります。Therefore, unlike JObject or JArray from Newtonsoft.Json, the JsonDocument type implements IDisposable and needs to be used inside a using block.

有効期間中全体の所有権を呼び出し元に移譲し、責任を破棄する場合は、API から JsonDocument のみを返します。Only return a JsonDocument from your API if you want to transfer lifetime ownership and dispose responsibility to the caller. ほとんどのシナリオでは、これは必要ありません。In most scenarios, that isn't necessary. 呼び出し元が JSON ドキュメント全体を操作する必要がある場合は、RootElement (つまり JsonElement) の Clone を返します。If the caller needs to work with the entire JSON document, return the Clone of the RootElement, which is a JsonElement. 呼び出し元が JSON ドキュメント内の特定の要素を操作する必要がある場合は、その JsonElementClone を返します。If the caller needs to work with a particular element within the JSON document, return the Clone of that JsonElement. Clone を作成せずに直接 RootElement またはサブ要素を返した場合、呼び出し元は、返された JsonElement には、それを所有する JsonDocument が破棄されるとアクセスできなくなります。If you return the RootElement or a sub-element directly without making a Clone, the caller won't be able to access the returned JsonElement after the JsonDocument that owns it is disposed.

Clone を作成する必要がある例を次に示します。Here's an example that requires you to make a Clone:

public JsonElement LookAndLoad(JsonElement source)
{
    string json = File.ReadAllText(source.GetProperty("fileName").GetString());

    using (JsonDocument doc = JsonDocument.Parse(json))
    {
        return doc.RootElement.Clone();
    }
}

上記のコードでは、fileName プロパティを含む JsonElement が想定されています。The preceding code expects a JsonElement that contains a fileName property. これにより、JSON ファイルが開き、JsonDocument が作成されます。It opens the JSON file and creates a JsonDocument. このメソッドでは、呼び出し元がドキュメント全体を操作することが想定されているため、RootElementClone が返されます。The method assumes that the caller wants to work with the entire document, so it returns the Clone of the RootElement.

JsonElement を受け取り、サブ要素を返す場合は、サブ要素の Clone を返す必要はありません。If you receive a JsonElement and are returning a sub-element, it's not necessary to return a Clone of the sub-element. 呼び出し元は、渡された JsonElement が属している JsonDocument が破棄されないように維持する役割を負っています。The caller is responsible for keeping alive the JsonDocument that the passed-in JsonElement belongs to. 次に例を示します。For example:

public JsonElement ReturnFileName(JsonElement source)
{
   return source.GetProperty("fileName");
}

JsonDocument は読み取り専用JsonDocument is read-only

System.Text.Json の DOM では、JSON 要素の追加、削除、変更を行うことはできません。The System.Text.Json DOM can't add, remove, or modify JSON elements. このように設計されている理由は、パフォーマンスを向上させ、一般的な JSON ペイロード サイズ (つまり、< 1 MB) を解析するための割り当てを減らすためです。It's designed this way for performance and to reduce allocations for parsing common JSON payload sizes (that is, < 1 MB). 現在のシナリオで変更可能な DOM を使用している場合は、次のいずれかの回避策を実行できる可能性があります。If your scenario currently uses a modifiable DOM, one of the following workarounds might be feasible:

  • JsonDocument を最初から作成する (つまり、既存の JSON ペイロードを Parse メソッドに渡さない場合) には、Utf8JsonWriter を使用して JSON テキストを記述し、そこからの出力を解析して新しい JsonDocument を作成します。To build a JsonDocument from scratch (that is, without passing in an existing JSON payload to the Parse method), write the JSON text by using the Utf8JsonWriter and parse the output from that to make a new JsonDocument.
  • 既存の JsonDocument を変更するには、それを使用して JSON テキストを記述し、記述中に変更を行い、そこからの出力を解析して新しい JsonDocument を作成します。To modify an existing JsonDocument, use it to write JSON text, making changes while you write, and parse the output from that to make a new JsonDocument.
  • 既存の JSON ドキュメントをマージする、つまり、Newtonsoft.JsonJObject.Merge または JContainer.Merge API と同等のことを行うには、この GitHub の問題を参照してください。To merge existing JSON documents, equivalent to the JObject.Merge or JContainer.Merge APIs from Newtonsoft.Json, see this GitHub issue.

JsonElement は union 構造体JsonElement is a union struct

JsonDocument では、JsonElement 型 (任意の JSON 要素を含む共用体の構造体型) のプロパティとして RootElement が公開されます。JsonDocument exposes the RootElement as a property of type JsonElement, which is a union, struct type that encompasses any JSON element. Newtonsoft.Json では JObjectJArrayJToken などの専用の階層型が使用されます。Newtonsoft.Json uses dedicated hierarchical types like JObject,JArray, JToken, and so forth. JsonElement に対して検索と列挙を行うことができます。また、JsonElement を使用して、JSON 要素を .NET 型に具体化することができます。JsonElement is what you can search and enumerate over, and you can use JsonElement to materialize JSON elements into .NET types.

JsonDocument と JsonElement でのサブ要素の検索方法How to search a JsonDocument and JsonElement for sub-elements

Newtonsoft.JsonJObject または JArray を使用した JSON トークンの検索は、何らかのディクショナリ内での検索であるため、比較的高速になる傾向があります。Searches for JSON tokens using JObject or JArray from Newtonsoft.Json tend to be relatively fast because they're lookups in some dictionary. それに対し、JsonElement での検索にはプロパティの順次検索が必要になるため、比較的低速になります (たとえば、TryGetProperty を使用する場合)。By comparison, searches on JsonElement require a sequential search of the properties and hence is relatively slow (for example when using TryGetProperty). System.Text.Json は、検索時間ではなく、初期解析時間を最小限に抑えるように設計されています。System.Text.Json is designed to minimize initial parse time rather than lookup time. そのため、JsonDocument オブジェクトで検索する場合は、次の方法を使用してパフォーマンスを最適化してください。Therefore, use the following approaches to optimize performance when searching through a JsonDocument object:

  • 独自のインデックス作成やループを実行するのではなく、組み込みの列挙子 (EnumerateArrayEnumerateObject) を使用します。Use the built-in enumerators (EnumerateArray and EnumerateObject) rather than doing your own indexing or loops.
  • RootElement を使用して、JsonDocument 全体ですべてのプロパティの順次検索を行わないでください。Don't do a sequential search on the whole JsonDocument through every property by using RootElement. 代わりに、JSON データの既知の構造に基づいて、入れ子になった JSON オブジェクトで検索します。Instead, search on nested JSON objects based on the known structure of the JSON data. たとえば、Student オブジェクトで Grade プロパティを探している場合は、Student オブジェクトをループし、それぞれの Grade の値を取得するようにします。すべての JsonElement オブジェクトで Grade プロパティを検索することは避けてください。For example, if you're looking for a Grade property in Student objects, loop through the Student objects and get the value of Grade for each, rather than searching through all JsonElement objects looking for Grade properties. 後者を行うと、同じデータに対して不要なパスが行われます。Doing the latter will result in unnecessary passes over the same data.

コード例については、「JsonDocument を使用してデータにアクセスする」を参照してください。For a code example, see Use JsonDocument for access to data.

JsonTextReader と比較した Utf8JsonReaderUtf8JsonReader compared to JsonTextReader

System.Text.Json.Utf8JsonReader は、UTF-8 でエンコードされた JSON テキスト用の、ハイ パフォーマンス、低割り当て、順方向専用のリーダーです。ReadOnlySpan<byte> または ReadOnlySequence<byte> から読み取られます。System.Text.Json.Utf8JsonReader is a high-performance, low allocation, forward-only reader for UTF-8 encoded JSON text, read from a ReadOnlySpan<byte> or ReadOnlySequence<byte>. Utf8JsonReader は低レベルの型であり、カスタム パーサーとデシリアライザーを構築するために使用できます。The Utf8JsonReader is a low-level type that can be used to build custom parsers and deserializers.

以下のセクションでは、Utf8JsonReader を使用する場合の推奨されるプログラミング パターンについて説明します。The following sections explain recommended programming patterns for using Utf8JsonReader.

Utf8JsonReader は ref 構造体Utf8JsonReader is a ref struct

Utf8JsonReader 型は " ref 構造体 " であるため、 特定の制限があります。Because the Utf8JsonReader type is a ref struct , it has certain limitations. たとえば、ref 構造体以外のクラスまたは構造体にフィールドとして格納することはできません。For example, it can't be stored as a field on a class or struct other than a ref struct. ハイ パフォーマンスを実現するには、この型が ref struct である必要があります。これは、入力の ReadOnlySpan<byte> (これ自体が ref 構造体です) をキャッシュする必要があるためです。To achieve high performance, this type must be a ref struct since it needs to cache the input ReadOnlySpan<byte>, which itself is a ref struct. さらに、この型は状態が保持されるため変更可能です。In addition, this type is mutable since it holds state. そのため、これは、値ではなく ref で渡してくださいTherefore, pass it by ref rather than by value. 値で渡すと、構造体のコピーが生成され、呼び出し元が状態の変更を確認できません。Passing it by value would result in a struct copy and the state changes would not be visible to the caller. これは Newtonsoft.Json とは異なります。Newtonsoft.Json JsonTextReader がクラスであるためです。This differs from Newtonsoft.Json since the Newtonsoft.Json JsonTextReader is a class. ref 構造体の使用方法の詳細については、「安全で効率的な C# コードを記述する」をご覧ください。For more information about how to use ref structs, see Write safe and efficient C# code.

UTF-8 テキストを読み取るRead UTF-8 text

Utf8JsonReader を使用しているときに最大限のパフォーマンスを達成するには、UTF-16 文字列としてではなく、UTF-8 テキストとして既にエンコードされている JSON ペイロードを読み取ります。To achieve the best possible performance while using the Utf8JsonReader, read JSON payloads already encoded as UTF-8 text rather than as UTF-16 strings. コード例については、「Utf8JsonReader を使用してデータをフィルター処理する」を参照してください。For a code example, see Filter data using Utf8JsonReader.

ストリームまたは PipeReader で読み取るRead with a Stream or PipeReader

Utf8JsonReader では、UTF-8 でエンコードされた ReadOnlySpan<byte> または ReadOnlySequence<byte> (これは PipeReader からの読み取りの結果です) からの読み取りがサポートされます。The Utf8JsonReader supports reading from a UTF-8 encoded ReadOnlySpan<byte> or ReadOnlySequence<byte> (which is the result of reading from a PipeReader).

同期読み取りの場合は、ストリームの末尾に到達するまで JSON ペイロードをバイト配列に読み込み、それをリーダーに渡すことができます。For synchronous reading, you could read the JSON payload until the end of the stream into a byte array and pass that into the reader. (UTF-16 としてエンコードされた) 文字列からの読み取りの場合は、UTF8.GetBytes を呼び出して、For reading from a string (which is encoded as UTF-16), call UTF8.GetBytes 最初にその文字列を UTF-8 でエンコードされたバイト配列にトランスコードします。to first transcode the string to a UTF-8 encoded byte array. その後、それを Utf8JsonReader に渡します。Then pass that to the Utf8JsonReader.

Utf8JsonReader では入力が JSON テキストと見なされるため、UTF-8 バイト オーダー マーク (BOM) は無効な JSON と見なされます。Since the Utf8JsonReader considers the input to be JSON text, a UTF-8 byte order mark (BOM) is considered invalid JSON. 呼び出し元は、それをフィルターで除外してからデータをリーダーに渡す必要があります。The caller needs to filter that out before passing the data to the reader.

コード例については、「Utf8JsonReader を使用する」を参照してください。For code examples, see Use Utf8JsonReader.

マルチセグメントの ReadOnlySequence で読み取るRead with multi-segment ReadOnlySequence

JSON の入力が ReadOnlySpan<byte> の場合、各 JSON 要素には、読み取りループを実行するときにリーダーの ValueSpan プロパティからアクセスできます。If your JSON input is a ReadOnlySpan<byte>, each JSON element can be accessed from the ValueSpan property on the reader as you go through the read loop. ただし、入力が ReadOnlySequence<byte> (これは、PipeReader からの読み取りの結果です) である場合、一部の JSON 要素が ReadOnlySequence<byte> オブジェクトの複数のセグメントにまたがることがあります。However, if your input is a ReadOnlySequence<byte> (which is the result of reading from a PipeReader), some JSON elements might straddle multiple segments of the ReadOnlySequence<byte> object. これらの要素には、連続メモリ ブロック内で ValueSpan からアクセスすることはできません。These elements would not be accessible from ValueSpan in a contiguous memory block. 代わりに、マルチセグメントの ReadOnlySequence<byte> を入力として使用する場合は必ず、リーダーで HasValueSequence プロパティをポーリングして、現在の JSON 要素へのアクセス方法を確認します。Instead, whenever you have a multi-segment ReadOnlySequence<byte> as input, poll the HasValueSequence property on the reader to figure out how to access the current JSON element. 推奨されるパターンを次に示します。Here's a recommended pattern:

while (reader.Read())
{
    switch (reader.TokenType)
    {
        // ...
        ReadOnlySpan<byte> jsonElement = reader.HasValueSequence ?
            reader.ValueSequence.ToArray() :
            reader.ValueSpan;
        // ...
    }
}

プロパティ名の検索に ValueTextEquals を使用するUse ValueTextEquals for property name lookups

プロパティ名の検索用に SequenceEqual を呼び出してバイト単位の比較を実行する場合は、ValueSpan を使用しないでください。Don't use ValueSpan to do byte-by-byte comparisons by calling SequenceEqual for property name lookups. 代わりに ValueTextEquals を呼び出してください。このメソッドにより、JSON でエスケープされた文字がエスケープ解除されるためです。Call ValueTextEquals instead, because that method unescapes any characters that are escaped in the JSON. 以下は、"name" という名前のプロパティの検索方法を示す例です。Here's an example that shows how to search for a property that is named "name":

private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
while (reader.Read())
{
    JsonTokenType tokenType = reader.TokenType;

    switch (tokenType)
    {
        case JsonTokenType.StartObject:
            total++;
            break;
        case JsonTokenType.PropertyName:
            if (reader.ValueTextEquals(s_nameUtf8))
            {
                count++;
            }
            break;
    }

null 許容値型に null 値を読み込むRead null values into nullable value types

Newtonsoft.Json には、Nullable<T> を返す API が用意されています。たとえば、bool? を返すことで Null TokenType を処理する ReadAsBoolean などがあります。Newtonsoft.Json provides APIs that return Nullable<T>, such as ReadAsBoolean, which handles a Null TokenType for you by returning a bool?. 組み込みの System.Text.Json の API では、null 非許容値型のみが返されます。The built-in System.Text.Json APIs return only non-nullable value types. たとえば、Utf8JsonReader.GetBoolean では bool が返されます。For example, Utf8JsonReader.GetBoolean returns a bool. JSON で Null が見つかると、例外がスローされます。It throws an exception if it finds Null in the JSON. 次の例は、null を処理する 2 つの方法を示しています。1 つは null 許容値型を返す方法で、もう 1 つは既定値を返す方法です。The following examples show two ways to handle nulls, one by returning a nullable value type and one by returning the default value:

public bool? ReadAsNullableBoolean()
{
    _reader.Read();
    if (_reader.TokenType == JsonTokenType.Null)
    {
        return null;
    }
    if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
    {
        throw new JsonException();
    }
    return _reader.GetBoolean();
}
public bool ReadAsBoolean(bool defaultValue)
{
    _reader.Read();
    if (_reader.TokenType == JsonTokenType.Null)
    {
        return defaultValue;
    }
    if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
    {
        throw new JsonException();
    }
    return _reader.GetBoolean();
}

マルチターゲットMulti-targeting

特定のターゲット フレームワークに対して Newtonsoft.Json の使用を継続する必要がある場合は、マルチターゲットにし、実装を 2 つにすることができます。If you need to continue to use Newtonsoft.Json for certain target frameworks, you can multi-target and have two implementations. ただし、これは簡単ではなく、いくつかの #ifdefs とソースの複製が必要になります。However, this is not trivial and would require some #ifdefs and source duplication. できるだけ多くのコードを共有する 1 つの方法として、Utf8JsonReaderNewtonsoft.Json JsonTextReader を囲む ref struct ラッパーを作成する方法があります。One way to share as much code as possible is to create a ref struct wrapper around Utf8JsonReader and Newtonsoft.Json JsonTextReader. このラッパーでは、動作の違いを隔離しつつ、公開されている表面部分は統合されます。This wrapper would unify the public surface area while isolating the behavioral differences. これにより、変更を主に型の構造に隔離すると共に、新しい型を参照によって渡すことができます。This lets you isolate the changes mainly to the construction of the type, along with passing the new type around by reference. これは、Microsoft.Extensions.DependencyModel ライブラリが従っているパターンです。This is the pattern that the Microsoft.Extensions.DependencyModel library follows:

JsonTextWriter と比較した Utf8JsonWriterUtf8JsonWriter compared to JsonTextWriter

System.Text.Json.Utf8JsonWriter は、StringInt32DateTime のような一般的な .NET 型から UTF-8 でエンコードされた JSON テキストを書き込むための、ハイパフォーマンスな方法です。System.Text.Json.Utf8JsonWriter is a high-performance way to write UTF-8 encoded JSON text from common .NET types like String, Int32, and DateTime. ライターは低レベルの型であり、カスタム シリアライザーを構築するために使用できます。The writer is a low-level type that can be used to build custom serializers.

以下のセクションでは、Utf8JsonWriter を使用する場合の推奨されるプログラミング パターンについて説明します。The following sections explain recommended programming patterns for using Utf8JsonWriter.

UTF-8 テキストで書き込むWrite with UTF-8 text

Utf8JsonWriter を使用しているときに最大限のパフォーマンスを達成するには、UTF-16 文字列としてではなく、UTF-8 テキストとして既にエンコードされている JSON ペイロードを書き込みます。To achieve the best possible performance while using the Utf8JsonWriter, write JSON payloads already encoded as UTF-8 text rather than as UTF-16 strings. UTF-16 文字列リテラルを使用するのではなく、JsonEncodedText を使用して、既知の文字列プロパティの名前と値をスタティックとしてキャッシュおよび事前エンコードし、ライターに渡します。Use JsonEncodedText to cache and pre-encode known string property names and values as statics, and pass those to the writer, rather than using UTF-16 string literals. これは、UTF-8 バイト配列をキャッシュして使用するより高速です。This is faster than caching and using UTF-8 byte arrays.

この方法は、カスタム エスケープ処理を行う必要がある場合にも機能します。This approach also works if you need to do custom escaping. System.Text.Json では、文字列の記述中にエスケープ処理を無効にすることはできません。System.Text.Json doesn't let you disable escaping while writing a string. ただし、独自のカスタム JavaScriptEncoder をオプションとしてライターに渡すことができます。または、JavascriptEncoder を使用する独自の JsonEncodedText を作成してエスケープ処理を行ってから、文字列の代わりに JsonEncodedText を書き込むこともできます。However, you could pass in your own custom JavaScriptEncoder as an option to the writer, or create your own JsonEncodedText that uses your JavascriptEncoder to do the escaping, and then write the JsonEncodedText instead of the string. 詳細については、「文字エンコードをカスタマイズする」を参照してください。For more information, see Customize character encoding.

生の値を書き込むWrite raw values

Newtonsoft.Json WriteRawValue メソッドでは、値が必要な生の JSON が書き込まれます。The Newtonsoft.Json WriteRawValue method writes raw JSON where a value is expected. System.Text.Json には、それに直接相当するものはありませんが、有効な JSON のみが書き込まれるようにする回避策を次に示します。System.Text.Json has no direct equivalent, but here's a workaround that ensures only valid JSON is written:

using JsonDocument doc = JsonDocument.Parse(string);
doc.WriteTo(writer);

文字のエスケープ処理をカスタマイズするCustomize character escaping

JsonTextWriterStringEscapeHandling 設定には、すべての ASCII 以外の文字 または HTML 文字をエスケープするオプションが用意されています。The StringEscapeHandling setting of JsonTextWriter offers options to escape all non-ASCII characters or HTML characters. 既定では、Utf8JsonWriter ではすべての ASCII 以外 および HTML 文字がエスケープされます。By default, Utf8JsonWriter escapes all non-ASCII and HTML characters. このエスケープ処理は、多層防御セキュリティ上の理由で行われます。This escaping is done for defense-in-depth security reasons. 別のエスケープ処理ポリシーを指定するには、JavaScriptEncoder を作成し、JsonWriterOptions.Encoder を設定します。To specify a different escaping policy, create a JavaScriptEncoder and set JsonWriterOptions.Encoder. 詳細については、「文字エンコードをカスタマイズする」を参照してください。For more information, see Customize character encoding.

JSON 形式をカスタマイズするCustomize JSON format

JsonTextWriter には次の設定が含まれていますが、Utf8JsonWriter には同等のものがありません。JsonTextWriter includes the following settings, for which Utf8JsonWriter has no equivalent:

  • Indentation - インデントする文字数を指定します。Indentation - Specifies how many characters to indent. Utf8JsonWriter では常に 2 文字のインデントが行われます。Utf8JsonWriter always does 2-character indentation.
  • IndentChar - インデントに使用する文字を指定します。IndentChar - Specifies the character to use for indentation. Utf8JsonWriter では常に空白文字が使用されます。Utf8JsonWriter always uses whitespace.
  • QuoteChar - 文字列値を囲むために使用する文字を指定します。QuoteChar - Specifies the character to use to surround string values. Utf8JsonWriter では常に二重引用符が使用されます。Utf8JsonWriter always uses double quotes.
  • QuoteName - プロパティ名を引用符で囲むかどうかを指定します。QuoteName - Specifies whether or not to surround property names with quotes. Utf8JsonWriter では常に引用符で囲みます。Utf8JsonWriter always surrounds them with quotes.

Utf8JsonWriter によって生成された JSON をこれらの方法でカスタマイズできる回避策はありません。There are no workarounds that would let you customize the JSON produced by Utf8JsonWriter in these ways.

null 値を書き込むWrite null values

Utf8JsonWriter を使用して null 値を書き込むには、以下を呼び出します。To write null values by using Utf8JsonWriter, call:

  • WriteNull。null を値として指定し、キーと値のペアを書き込みます。WriteNull to write a key-value pair with null as the value.
  • WriteNullValue。JSON 配列の要素として null を書き込みます。WriteNullValue to write null as an element of a JSON array.

文字列プロパティでは、文字列が null の場合、WriteStringWriteStringValueWriteNullWriteNullValue に相当します。For a string property, if the string is null, WriteString and WriteStringValue are equivalent to WriteNull and WriteNullValue.

Timespan、Uri、または char の値を書き込むWrite Timespan, Uri, or char values

JsonTextWriter には、TimeSpanUrichar の値のための WriteValue メソッドがあります。JsonTextWriter provides WriteValue methods for TimeSpan, Uri, and char values. Utf8JsonWriter には同等のメソッドがありません。Utf8JsonWriter doesn't have equivalent methods. 代わりに、これらの値を文字列として書式設定し (たとえば ToString() を呼び出します)、WriteStringValue を呼び出します。Instead, format these values as strings (by calling ToString(), for example) and call WriteStringValue.

マルチターゲットMulti-targeting

特定のターゲット フレームワークに対して Newtonsoft.Json の使用を継続する必要がある場合は、マルチターゲットにし、実装を 2 つにすることができます。If you need to continue to use Newtonsoft.Json for certain target frameworks, you can multi-target and have two implementations. ただし、これは簡単ではなく、いくつかの #ifdefs とソースの複製が必要になります。However, this is not trivial and would require some #ifdefs and source duplication. できるだけ多くのコードを共有する 1 つの方法として、Utf8JsonWriterNewtonsoft JsonTextWriter を囲むラッパーを作成する方法があります。One way to share as much code as possible is to create a wrapper around Utf8JsonWriter and Newtonsoft JsonTextWriter. このラッパーでは、動作の違いを隔離しつつ、公開されている表面部分は統合されます。This wrapper would unify the public surface area while isolating the behavioral differences. これにより、主に型の構造に変更を隔離できます。This lets you isolate the changes mainly to the construction of the type. Microsoft.Extensions.DependencyModel ライブラリは以下に従っています。Microsoft.Extensions.DependencyModel library follows:

その他の技術情報Additional resources