System.Text.Json でサポートされているコレクション型

この記事では、どのコレクションでシリアル化および逆シリアル化がサポートされているかを概説します。 System.Text.Json.JsonSerializer では、次の場合にシリアル化用のコレクション型をサポートしています。

  • IEnumerableから派生します。
  • シリアル化可能な要素が含まれている。

シリアライザーが GetEnumerator() メソッドを呼び出し、その要素を書き込みます。

逆シリアル化はこれよりも複雑であり、一部のコレクション型ではサポートされていません。

次のセクションでは、名前空間ごとに、シリアル化と逆シリアル化がサポートされている型を示します。

System.Array 名前空間

種類 シリアル化 逆シリアル化
1 次元配列 ✔️ ✔️
多次元配列
ジャグ配列 ✔️ ✔️

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> ✔️ ✔️
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> についての次のセクションを参照してください。

IAsyncEnumerable<T>

次の例では、データの非同期ソースの表現としてストリームを使用します。 ソースは、ローカル コンピューター上のファイルでも、データベース クエリまたは Web サービス API 呼び出しの結果でもかまいません。

ストリームのシリアル化

System.Text.Json では、次の例に示すように、JSON 配列としての IAsyncEnumerable<T> 値のシリアル化がサポートされています。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;

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 などの非同期シリアル化メソッドでのみサポートされます。

ストリームの逆シリアル化

次の例に示すように、DeserializeAsyncEnumerable メソッドにより、ストリーミングの逆シリアル化がサポートされます。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace IAsyncEnumerableDeserialize
{
    public class Program
    {
        public static async Task Main()
        {
            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

DeserializeAsyncEnumerable メソッドでは、ルート レベルの JSON 配列からの読み取りのみがサポートされます。

DeserializeAsync メソッドにより IAsyncEnumerable<T> はサポートされますが、そのシグネチャではストリーミングは許可されません。 次の例で示すように、最終的な結果は 1 つの値として返されます。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace IAsyncEnumerableDeserializeNonStreaming
{
    public class MyPoco
    {
        public IAsyncEnumerable<int> Data { get; set; }
    }

    public class Program
    {
        public static async Task Main()
        {
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
            var 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 ペイロード全体を読み取る必要があるために必要です。

種類 シリアル化 逆シリアル化
Dictionary<TKey,TValue> * ✔️ ✔️
HashSet<T> ✔️ ✔️
IAsyncEnumerable<T>
ICollection<T> ✔️ ✔️
IDictionary<TKey,TValue> * ✔️ ✔️
IEnumerable<T> ✔️ ✔️
IList<T> ✔️ ✔️
IReadOnlyCollection<T> ✔️ ✔️
IReadOnlyDictionary<TKey,TValue> * ✔️ ✔️
IReadOnlyList<T> ✔️ ✔️
ISet<T> ✔️ ✔️
KeyValuePair<TKey,TValue> ✔️ ✔️
LinkedList<T> ✔️ ✔️
LinkedListNode<T> ✔️
List<T> ✔️ ✔️
Queue<T> ✔️ ✔️
SortedDictionary<TKey,TValue> * ✔️ ✔️
SortedList<TKey,TValue> * ✔️ ✔️
SortedSet<T> ✔️ ✔️
Stack<T> ✔️ ✔️

* 「サポートされているキーの種類」を参照してください。

種類 シリアル化 逆シリアル化
Dictionary<string, TValue> * ✔️ ✔️
HashSet<T> ✔️ ✔️
IAsyncEnumerable<T>
ICollection<T> ✔️ ✔️
IDictionary<string, TValue> * ✔️ ✔️
IEnumerable<T> ✔️ ✔️
IList<T> ✔️ ✔️
IReadOnlyCollection<T> ✔️ ✔️
IReadOnlyDictionary<string, TValue> * ✔️ ✔️
IReadOnlyList<T> ✔️ ✔️
ISet<T> ✔️ ✔️
KeyValuePair<TKey,TValue> ✔️ ✔️
LinkedList<T> ✔️ ✔️
LinkedListNode<T> ✔️
List<T> ✔️ ✔️
Queue<T> ✔️ ✔️
SortedDictionary<string, TValue> * ✔️ ✔️
SortedList<string, TValue> * ✔️ ✔️
SortedSet<T> ✔️ ✔️
Stack<T> ✔️ ✔️

* 「サポートされているキーの種類」を参照してください。

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> * ✔️ ✔️
種類 シリアル化 逆シリアル化
IImmutableDictionary<string, TValue> ** ✔️ ✔️
IImmutableList<T> ✔️ ✔️
IImmutableQueue<T> ✔️ ✔️
IImmutableSet<T> ✔️ ✔️
IImmutableStack<T> * ✔️ ✔️
ImmutableArray<T> ✔️ ✔️
ImmutableDictionary<string, TValue> ** ✔️ ✔️
ImmutableHashSet<T> ✔️ ✔️
IImmutableList<T> ✔️ ✔️
ImmutableQueue<T> ✔️ ✔️
ImmutableSortedDictionary<string, TValue> ** ✔️ ✔️
ImmutableSortedSet<T> ✔️ ✔️
ImmutableStack<T> * ✔️ ✔️

* 「Stack<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> * ✔️ ✔️
種類 シリアル化 逆シリアル化
BlockingCollection<T> ✔️
ConcurrentBag<T> ✔️
ConcurrentDictionary<string, TValue> ** ✔️ ✔️
ConcurrentQueue<T> ✔️ ✔️
ConcurrentStack<T> * ✔️ ✔️

* 「Stack<T> のラウンド トリップをサポートする」を参照してください。

* 「*サポートされているキーの種類」を参照してください

System.Collections.ObjectModel 名前空間

種類 シリアル化 逆シリアル化
Collection<T> ✔️ ✔️
KeyedCollection<string, TValue> * ✔️
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️
ReadOnlyDictionary<TKey,TValue> ✔️
ReadOnlyObservableCollection<T> ✔️

* string ではないキーはサポートされていません。

種類 シリアル化 逆シリアル化
Collection<T> ✔️ ✔️
KeyedCollection<string, TValue> * ✔️
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️
ReadOnlyDictionary<string, TValue> * ✔️
ReadOnlyObservableCollection<T> ✔️

* 「サポートされているキーの種類」を参照してください。

カスタム コレクション

上記のいずれの名前空間にも含まれないコレクション型は、カスタム コレクションと見なされます。 このような型には、ユーザー定義型と ASP.NET Core で定義されている型が含まれます。 たとえば、このグループには Microsoft.Extensions.Primitives があります。

すべてのカスタム コレクション (IEnumerable から派生するすべてのもの) は、その要素の型がサポートされている限り、シリアル化でサポートされます。

逆シリアル化がサポートされているカスタム コレクション

次の場合、逆シリアル化にカスタム コレクションがサポートされます。

* 「Stack<T> のラウンド トリップをサポートする」を参照してください。

* 「*サポートされているキーの種類」を参照してください

既知の問題があるカスタム コレクション

次のカスタム コレクションには既知の問題があります。

既知の問題の詳細については、System.Text.Json のオープンのイシューに関するページを参照してください。

サポートされているキーの種類

Dictionary および SortedList 型のキーには、次の型がサポートされています。

  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object (シリアル化と、ランタイム型がこの一覧でサポートされている型のいずれかである場合のみ)。
  • SByte
  • Single
  • String
  • UInt16
  • UInt32
  • UInt64

** .NET Core 3.1 では、Dictionary および SortedList 型に string ではないキーはサポートされていません。

System.Data 名前空間

System.Data 名前空間には、DataSetDataTable、および関連する型用の組み込みコンバーターはありません。 セキュリティ ガイダンスで説明されているように、信頼できない入力からこれらの型を逆シリアル化することは安全ではありません。 ただし、これらの型をサポートするカスタム コンバーターを作成することはできます。 DataTable をシリアル化および逆シリアル化するカスタム コンバーター コードのサンプルについては、RoundtripDataTable.cs を参照してください。

関連項目