この記事では、シリアル化と逆シリアル化でサポートされる型の概要について説明します。
JSON オブジェクトとしてシリアル化する型
次の型は JSON オブジェクトとしてシリアル化されます。
- クラス*
- 構造体
- インターフェイス
- レコードと構造体レコード
* JSON 配列としてシリアル化 IEnumerable<T> 実装する非ディクショナリ型。 IEnumerable<T>を実装するディクショナリ型は、JSON オブジェクトとしてシリアル化されます。
次のコード スニペットは、単純な構造体のシリアル化を示しています。
public static void Main()
{
var coordinates = new Coords(1.0, 2.0);
string json = JsonSerializer.Serialize(coordinates);
Console.WriteLine(json);
// Output:
// {"X":1,"Y":2}
}
public readonly struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get; }
public double Y { get; }
}
JSON 配列としてシリアル化する型
.NET コレクション型は JSON 配列としてシリアル化されます。 System.Text.Json.JsonSerializer は、次の場合にシリアル化のコレクション型をサポートします。
- IEnumerable または IAsyncEnumerable<T>から派生します。
- シリアル化可能な要素が含まれています。
シリアライザーは、GetEnumerator() メソッドを呼び出し、要素を書き込みます。
逆シリアル化はより複雑であり、一部のコレクション型ではサポートされていません。
次のセクションでは、名前空間別に整理し、シリアル化と逆シリアル化でサポートされる型を示します。
- System.Array 名前空間の
- System.Collections 名前空間の
- System.Collections.Generic 名前空間の
- System.Collections.Immutable 名前空間
- System.Collections.Specialized 名前空間の
- System.Collections.Concurrent 名前空間の
- System.Collections.ObjectModel 名前空間
- カスタム コレクション の
System.Array 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| 1 次元配列* | ✔️ | ✔️ |
| 多次元配列 | ❌ | ❌ |
| ジャグ配列 | ✔️ | ✔️ |
*
byte[] は特別に処理され、JSON 配列ではなく base64 文字列としてシリアル化されます。
System.Collections 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| ArrayList | ✔️ | ✔️ |
| BitArray | ✔️ | ❌ |
| DictionaryEntry | ✔️ | ✔️ |
| Hashtable | ✔️ | ✔️ |
| ICollection | ✔️ | ✔️ |
| IDictionary | ✔️ | ✔️ |
| IEnumerable | ✔️ | ✔️ |
| IList | ✔️ | ✔️ |
| Queue | ✔️ | ✔️ |
| SortedList | ✔️ | ✔️ |
| Stack * | ✔️ | ✔️ |
*
System.Collections.Generic 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| Dictionary<TKey,TValue> * | ✔️ | ✔️ |
| HashSet<T> | ✔️ | ✔️ |
| IAsyncEnumerable<T> † | ✔️ | ✔️ |
| ICollection<T> | ✔️ | ✔️ |
| IDictionary<TKey,TValue> * | ✔️ | ✔️ |
| IEnumerable<T> | ✔️ | ✔️ |
| IList<T> | ✔️ | ✔️ |
| IReadOnlyCollection<T> | ✔️ | ✔️ |
| IReadOnlyDictionary<TKey,TValue> * | ✔️ | ✔️ |
| IReadOnlyList<T> | ✔️ | ✔️ |
| IReadOnlySet<T> § | ✔️ | ✔️ |
| ISet<T> | ✔️ | ✔️ |
| KeyValuePair<TKey,TValue> | ✔️ | ✔️ |
| LinkedList<T> | ✔️ | ✔️ |
| LinkedListNode<T> | ✔️ | ❌ |
| List<T> | ✔️ | ✔️ |
| Queue<T> | ✔️ | ✔️ |
| SortedDictionary<TKey,TValue> * | ✔️ | ✔️ |
| SortedList<TKey,TValue> * | ✔️ | ✔️ |
| SortedSet<T> | ✔️ | ✔️ |
| Stack<T> ‡ | ✔️ | ✔️ |
*サポートされているキーの種類のを参照してください。
† IAsyncEnumerable<T>の次のセクションを参照してください。
‡Stack タイプのラウンドトリップをサポートするを参照してください。
§ System.Text.Json では、.NET 11 以降のバージョンでのIReadOnlySet<T>がサポートされています。 インターフェイスを逆シリアル化すると、シリアライザーによって HashSet<T> インスタンスが作成されます。 生成されたメタデータの場合、 JsonMetadataServices.CreateIReadOnlySetInfo はコレクション コントラクトを作成します。
IAsyncEnumerable<T>
次の例では、データの非同期ソースの表現としてストリームを使用します。 ソースは、ローカル コンピューター上のファイル、またはデータベース クエリまたは Web サービス API 呼び出しの結果である可能性があります。
ストリームのシリアル化
System.Text.Json では、次の例に示すように、IAsyncEnumerable<T> 値を JSON 配列としてシリアル化できます。
using System.Text.Json;
namespace IAsyncEnumerableSerialize;
public class Program
{
public static async Task Main()
{
using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data);
}
static async IAsyncEnumerable<int> PrintNumbers(int n)
{
for (int i = 0; i < n; i++)
{
await Task.Delay(1000);
yield return i;
}
}
}
// output:
// {"Data":[0,1,2]}
IAsyncEnumerable<T> 値は、JsonSerializer.SerializeAsyncなどの非同期シリアル化メソッドでのみサポートされます。
.NET 11 以降のバージョンでは、JsonSerializer.SerializeAsyncEnumerableはIAsyncEnumerable<T> シーケンスをStreamまたはPipeWriterに書き込みます。 既定の topLevelValues: falseでは、このメソッドは単一のルート レベルの JSON 配列を書き込みます。 代わりに JSON 行を書き込むtopLevelValues: trueを設定します。各要素は別の最上位レベルの値です。
{"id":1,"name":"apple"}
{"id":2,"name":"banana"}
メソッドは、1 つの改行 (LF) \n、最後を含むすべての値の後に書き込みます。
JsonSerializerOptions.NewLineに関係なく、常に LF を使用します。 メソッドは JsonSerializerOptions.WriteIndentedを無視するため、各値は 1 行に残ります。
ストリームの逆シリアル化
DeserializeAsyncEnumerable メソッドは、次の例に示すように、ストリーミング逆シリアル化をサポートしています。
using System.Text;
using System.Text.Json;
namespace IAsyncEnumerableDeserialize;
public class Program
{
public static async Task Main()
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream))
{
Console.WriteLine(item);
}
}
}
// output:
//0
//1
//2
//3
//4
既定では、 JsonSerializer.DeserializeAsyncEnumerable は 1 つのルート レベルの JSON 配列から要素を読み取ります。 代わりに、空白で区切られた最上位レベルの値のシーケンスを読み取る topLevelValues: true を設定します。 この入力形式は、JSON 行のスーパーセットです。 オーバーロードは、 Stream または PipeReaderを受け入れます。
DeserializeAsync メソッドは IAsyncEnumerable<T>をサポートしていますが、そのシグネチャではストリーミングが許可されません。 次の例に示すように、最終的な結果は 1 つの値として返されます。
using System.Text;
using System.Text.Json;
namespace IAsyncEnumerableDeserializeNonStreaming;
public class MyPoco
{
public IAsyncEnumerable<int>? Data { get; set; }
}
public class Program
{
public static async Task Main()
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
MyPoco? result = await JsonSerializer.DeserializeAsync<MyPoco>(stream)!;
await foreach (int item in result!.Data!)
{
Console.WriteLine(item);
}
}
}
// output:
//0
//1
//2
//3
//4
この例では、逆シリアライザーは、逆シリアル化されたオブジェクトを返す前に、メモリ内のすべての IAsyncEnumerable<T> コンテンツをバッファーします。 逆シリアライザーは結果を返す前に JSON ペイロード全体を読み取る必要があるため、この動作が必要です。
System.Collections.Immutable 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| IImmutableDictionary<TKey,TValue> † | ✔️ | ✔️ |
| IImmutableList<T> | ✔️ | ✔️ |
| IImmutableQueue<T> | ✔️ | ✔️ |
| IImmutableSet<T> | ✔️ | ✔️ |
| IImmutableStack<T> * | ✔️ | ✔️ |
| ImmutableArray<T> | ✔️ | ✔️ |
| ImmutableDictionary<TKey,TValue> † | ✔️ | ✔️ |
| ImmutableHashSet<T> | ✔️ | ✔️ |
| ImmutableQueue<T> | ✔️ | ✔️ |
| ImmutableSortedDictionary<TKey,TValue> † | ✔️ | ✔️ |
| ImmutableSortedSet<T> | ✔️ | ✔️ |
| ImmutableStack<T> * | ✔️ | ✔️ |
*
† サポート キーの種類のを参照してください。
System.Collections.Specialized 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| BitVector32 | ✔️ | ❌* |
| HybridDictionary | ✔️ | ✔️ |
| IOrderedDictionary | ✔️ | ❌ |
| ListDictionary | ✔️ | ✔️ |
| NameValueCollection | ✔️ | ❌ |
| StringCollection | ✔️ | ❌ |
| StringDictionary | ✔️ | ❌ |
* BitVector32 を逆シリアル化すると、パブリック セッターがないため、Data プロパティはスキップされます。 例外はスローされません。
System.Collections.Concurrent 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| BlockingCollection<T> | ✔️ | ❌ |
| ConcurrentBag<T> | ✔️ | ❌ |
| ConcurrentDictionary<TKey,TValue> † | ✔️ | ✔️ |
| ConcurrentQueue<T> | ✔️ | ✔️ |
| ConcurrentStack<T> * | ✔️ | ✔️ |
*
† サポート キーの種類のを参照してください。
System.Collections.ObjectModel 名前空間
| タイプ | 連載 | 逆シリアル化 |
|---|---|---|
| Collection<T> | ✔️ | ✔️ |
| KeyedCollection<文字列、TValue> * | ✔️ | ❌ |
| ObservableCollection<T> | ✔️ | ✔️ |
| ReadOnlyCollection<T> | ✔️ | ❌ |
| ReadOnlyDictionary<TKey,TValue> | ✔️ | ❌ |
| ReadOnlyObservableCollection<T> | ✔️ | ❌ |
*string 以外のキーはサポートされていません。
カスタム コレクション
上記のいずれかの名前空間にないコレクション型は、カスタム コレクションと見なされます。 このような型には、ユーザー定義型と、ASP.NET Core によって定義された型が含まれます。 たとえば、Microsoft.Extensions.Primitives はこのグループに含まれます。
要素型がサポートされている限り、すべてのカスタム コレクション (IEnumerableから派生するすべてのコレクション) はシリアル化でサポートされます。
逆シリアル化のサポート
カスタム コレクションは、次の場合に逆シリアル化でサポートされます。
インターフェイスまたは抽象ではありません。
パラメーターなしのコンストラクターがあります。
JsonSerializerでサポートされている要素型が含まれています。
次の 1 つ以上のインターフェイスまたはクラスを実装または継承します。
- ConcurrentQueue<T>
- ConcurrentStack<T> *
- ICollection<T>
- IDictionary
- IDictionary<TKey,TValue> †
- IList
- IList<T>
- Queue
- Queue<T>
- Stack *
- Stack<T> *
*
タイプの サポートラウンドトリップを参照してください。 † サポート キーの種類のを参照してください。
既知の問題
次のカスタム コレクションには既知の問題があります。
: dotnet/runtime#29690 を参照してください。 : dotnet/runtime#1808 を参照してください。 - DataTable: dotnet/docs#21366を参照してください。
: dotnet/runtime#1559 を参照してください。 : dotnet/runtime#1559 を参照してください。
既知の問題の詳細については、
サポートされているキーの種類
Dictionary 型と SortedList 型のキーとして使用する場合、次の型に組み込みのサポートがあります。
- BFloat16(.NET 11 以降)
BooleanByteDateTimeDateTimeOffsetDecimal- Decimal32(.NET 11 以降)
- Decimal64(.NET 11 以降)
- Decimal128(.NET 11 以降)
DoubleEnumGuidInt16Int32Int64-
Object(シリアル化でのみ、ランタイム型がこの一覧でサポートされている型の 1 つである場合)。 SByteSingleString- TimeSpan
UInt16UInt32UInt64- Uri
- Version
さらに、JsonConverter<T>.WriteAsPropertyName(Utf8JsonWriter, T, JsonSerializerOptions) メソッドと JsonConverter<T>.ReadAsPropertyName(Utf8JsonReader, Type, JsonSerializerOptions) メソッドを使用すると、任意の種類の辞書キーのサポートを追加できます。
BFloat16 型と 10 進浮動小数点型
.NET 11 以降、System.Text.Jsonには、BFloat16、Decimal32、Decimal64、およびDecimal128型の組み込みコンバーターが含まれています。 有限値は JSON 数値としてシリアル化されます。
これらの型は、他の組み込みの数値型と同様に動作します。
- ディクショナリ キー変換では、4 種類すべてがサポートされます。
-
AllowNamedFloatingPointLiteralsを通じて、
"NaN"、"Infinity"、および"-Infinity"リテラルを含むJsonNumberHandlingを尊重します。
JsonMetadataServices では、ソース生成メタデータのコンバーター プロパティが公開されます。 プロパティは JsonMetadataServices.BFloat16Converter、JsonMetadataServices.Decimal32Converter、JsonMetadataServices.Decimal64Converter、JsonMetadataServices.Decimal128Converter です。
F# 判別共用体
.NET 11 以降では、System.Text.Jsonは、クラス、構造体、再帰共用体を含む F# 判別共用体をシリアル化および逆シリアル化します。
type Shape =
| Point
| Circle of radius: float
- フィールドのないケースは、
"Point"などのケース名を含む JSON 文字列としてシリアル化されます。 - フィールドが JSON オブジェクトとしてシリアル化されるケース。 オブジェクトには、
$type識別子の後にケースの名前付きフィールド ({"$type":"Circle","radius":3.14}など) が含まれます。
JsonSerializerOptions.PropertyNamingPolicy は、大文字と小文字の名前とフィールド名に適用されます。 ケース レベルの JsonPropertyNameAttribute が優先されます。
$type以外の識別子プロパティ名を使用するには、JsonPolymorphicAttribute.TypeDiscriminatorPropertyName設定します。
Important
F# 判別共用体のサポートはリフレクション専用です。 動的なコードと未作成のリフレクション メタデータが必要です。
System.Text.Jsonソース生成またはネイティブ AOT では使用できません。
サポートされていない型
シリアル化では、次の種類はサポートされていません。
- System.Type と System.Reflection.MemberInfo
- ReadOnlySpan<T>、Span<T>、および ref 構造体全般
- デリゲート型
- IntPtr と UIntPtr
System.Data 名前空間
DataSet 名前空間には、DataTable、System.Data、および関連する型用の組み込みコンバーターはありません。 セキュリティ ガイダンスで説明されているように、これらの型を信頼されていない入力から逆シリアル化 DataTableをシリアル化および逆シリアル化するカスタム コンバーター コードのサンプルについては、RoundtripDataTable.csを参照してください。
関連項目
.NET