.NET で JSON のシリアル化と逆シリアル化 (マーシャリングとマーシャリング解除) を行う方法How to serialize and deserialize (marshal and unmarshal) JSON in .NET

この記事では、System.Text.Json 名前空間を使用して、JavaScript Object Notation (JSON) との間でシリアル化および逆シリアル化を行う方法について説明します。This article shows how to use the System.Text.Json namespace to serialize and deserialize to and from JavaScript Object Notation (JSON).

指示とサンプルコードは、ライブラリを直接使用します。 ASP.NET Coreなどのフレームワークでは使用されません。The directions and sample code use the library directly, not through a framework such as ASP.NET Core.

シリアル化のサンプルコードの大部分では、JSON を "見栄えよく" するように trueJsonSerializerOptions.WriteIndented を設定します (ユーザーが読みやすくするためにインデントと空白文字が使用されます)。Most of the serialization sample code sets JsonSerializerOptions.WriteIndented to true to "pretty-print" the JSON (with indentation and whitespace for human readability). 実稼働環境で使用する場合は、通常、この設定の false の既定値をそのまま使用します。For production use, you would typically accept the default value of false for this setting.

名前空間Namespaces

System.Text.Json 名前空間には、すべてのエントリポイントと主要な型が含まれます。The System.Text.Json namespace contains all the entry points and the main types. System.Text.Json.Serialization 名前空間には、シリアル化と逆シリアル化に固有の高度なシナリオとカスタマイズのための属性と Api が含まれています。The System.Text.Json.Serialization namespace contains attributes and APIs for advanced scenarios and customization specific to serialization and deserialization. この記事に示されているコード例では、次のいずれかまたは両方の名前空間に using ディレクティブが必要です。The code examples shown in this article require using directives for one or both of these namespaces:

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

System.Runtime.Serialization 名前空間の属性は、現在 System.Text.Jsonではサポートされていません。Attributes from the System.Runtime.Serialization namespace aren't currently supported in System.Text.Json.

.NET オブジェクトを JSON に書き込む方法 (シリアル化)How to write .NET objects to JSON (serialize)

JSON を文字列またはファイルに書き込むには、JsonSerializer.Serialize メソッドを呼び出します。To write JSON to a string or to a file, call the JsonSerializer.Serialize method.

次の例では、JSON を文字列として作成します。The following example creates JSON as a string:

string jsonString;
jsonString = JsonSerializer.Serialize(weatherForecast);

次の例では、同期コードを使用して JSON ファイルを作成します。The following example uses synchronous code to create a JSON file:

jsonString = JsonSerializer.Serialize(weatherForecast);
File.WriteAllText(fileName, jsonString);

次の例では、非同期コードを使用して JSON ファイルを作成します。The following example uses asynchronous code to create a JSON file:

using (FileStream fs = File.Create(fileName))
{
    await JsonSerializer.SerializeAsync(fs, weatherForecast);
}

前の例では、シリアル化する型の型の推定を使用します。The preceding examples use type inference for the type being serialized. Serialize() のオーバーロードは、ジェネリック型パラメーターを受け取ります。An overload of Serialize() takes a generic type parameter:

jsonString = JsonSerializer.Serialize<WeatherForecastWithPOCOs>(weatherForecast);

シリアル化の例Serialization example

コレクションと入れ子になったクラスを含むクラスの例を次に示します。Here's an example class that contains collections and a nested class:

public class WeatherForecastWithPOCOs
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    public string SummaryField;
    public IList<DateTimeOffset> DatesAvailable { get; set; }
    public Dictionary<string, HighLowTemps> TemperatureRanges { get; set; }
    public string[] SummaryWords { get; set; }
}

public class HighLowTemps
{
    public int High { get; set; }
    public int Low { get; set; }
}

前の型のインスタンスをシリアル化した JSON 出力は、次の例のようになります。The JSON output from serializing an instance of the preceding type looks like the following example. 既定では、JSON 出力が縮小されます。The JSON output is minified by default:

{"Date":"2019-08-01T00:00:00-07:00","TemperatureCelsius":25,"Summary":"Hot","DatesAvailable":["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"TemperatureRanges":{"Cold":{"High":20,"Low":-10},"Hot":{"High":60,"Low":20}},"SummaryWords":["Cool","Windy","Humid"]}

次の例では、同じ JSON が書式設定されています (空白とインデントで整形されています)。The following example shows the same JSON, formatted (that is, pretty-printed with whitespace and indentation):

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "DatesAvailable": [
    "2019-08-01T00:00:00-07:00",
    "2019-08-02T00:00:00-07:00"
  ],
  "TemperatureRanges": {
    "Cold": {
      "High": 20,
      "Low": -10
    },
    "Hot": {
      "High": 60,
      "Low": 20
    }
  },
  "SummaryWords": [
    "Cool",
    "Windy",
    "Humid"
  ]
}

UTF-8 にシリアル化するSerialize to UTF-8

UTF-8 にシリアル化するには、JsonSerializer.SerializeToUtf8Bytes メソッドを呼び出します。To serialize to UTF-8, call the JsonSerializer.SerializeToUtf8Bytes method:

byte[] jsonUtf8Bytes;
var options = new JsonSerializerOptions
{
    WriteIndented = true
};
jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(weatherForecast, options);

Utf8JsonWriter を受け取る Serialize のオーバーロードも使用できます。A Serialize overload that takes a Utf8JsonWriter is also available.

UTF-8 へのシリアル化は、文字列ベースのメソッドを使用するよりも約5-10% 高速です。Serializing to UTF-8 is about 5-10% faster than using the string-based methods. 違いは、バイト (UTF-8) を文字列 (UTF-16) に変換する必要がないためです。The difference is because the bytes (as UTF-8) don't need to be converted to strings (UTF-16).

シリアル化の動作Serialization behavior

サポートされている種類は次のとおりです。Supported types include:

  • 数値型、文字列、ブール値など、JavaScript プリミティブにマップされる .NET プリミティブ。.NET primitives that map to JavaScript primitives, such as numeric types, strings, and Boolean.
  • ユーザー定義のPlain OLD CLR オブジェクト (POCOs)User-defined Plain Old CLR Objects (POCOs).
  • 1次元配列とジャグ配列 (ArrayName[][])。One-dimensional and jagged arrays (ArrayName[][]).
  • Dictionary<string,TValue> TValueobjectJsonElement、または POCO です。Dictionary<string,TValue> where TValue is object, JsonElement, or a POCO.
  • 次の名前空間のコレクション。Collections from the following namespaces.

カスタムコンバーターを実装して、追加の型を処理したり、組み込みのコンバーターでサポートされていない機能を提供したりすることができます。You can implement custom converters to handle additional types or to provide functionality that isn't supported by the built-in converters.

JSON を .NET オブジェクトに読み込む方法 (逆シリアル化)How to read JSON into .NET objects (deserialize)

文字列またはファイルから逆シリアル化するには、JsonSerializer.Deserialize メソッドを呼び出します。To deserialize from a string or a file, call the JsonSerializer.Deserialize method.

次の例では、文字列から JSON を読み取り、シリアル化の例で前に示した WeatherForecast クラスのインスタンスを作成します。The following example reads JSON from a string and creates an instance of the WeatherForecast class shown earlier for the serialization example:

weatherForecast = JsonSerializer.Deserialize<WeatherForecastWithPOCOs>(jsonString);

同期コードを使用してファイルから逆シリアル化するには、次の例に示すように、ファイルを文字列に読み取ります。To deserialize from a file by using synchronous code, read the file into a string, as shown in the following example:

jsonString = File.ReadAllText(fileName);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);

非同期コードを使用してファイルから逆シリアル化するには、DeserializeAsync メソッドを呼び出します。To deserialize from a file by using asynchronous code, call the DeserializeAsync method:

using (FileStream fs = File.OpenRead(fileName))
{
    weatherForecast = await JsonSerializer.DeserializeAsync<WeatherForecast>(fs);
}

UTF-8 からの逆シリアル化Deserialize from UTF-8

UTF-8 から逆シリアル化するには、次の例に示すように、Utf8JsonReader または ReadOnlySpan<byte>を受け取る JsonSerializer.Deserialize オーバーロードを呼び出します。To deserialize from UTF-8, call a JsonSerializer.Deserialize overload that takes a Utf8JsonReader or a ReadOnlySpan<byte>, as shown in the following examples. この例では、JSON が jsonUtf8Bytes という名前のバイト配列にあることを前提としています。The examples assume the JSON is in a byte array named jsonUtf8Bytes.

var readOnlySpan = new ReadOnlySpan<byte>(jsonUtf8Bytes);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(readOnlySpan);
var utf8Reader = new Utf8JsonReader(jsonUtf8Bytes);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(ref utf8Reader);

逆シリアル化の動作Deserialization behavior

  • 既定では、プロパティ名の照合では大文字と小文字が区別されます。By default, property name matching is case-sensitive. 大文字と小文字を区別しないように指定できます。You can specify case-insensitivity.
  • JSON に読み取り専用プロパティの値が含まれている場合、この値は無視され、例外はスローされません。If the JSON contains a value for a read-only property, the value is ignored and no exception is thrown.
  • パラメーターなしのコンストラクターを使用しない参照型への逆シリアル化はサポートされていません。Deserialization to reference types without a parameterless constructor isn't supported.
  • 変更できないオブジェクトまたは読み取り専用プロパティへの逆シリアル化はサポートされていません。Deserialization to immutable objects or read-only properties isn't supported.
  • 既定では、列挙型は数値としてサポートされています。By default, enums are supported as numbers. 列挙型名を文字列としてシリアル化できます。You can serialize enum names as strings.
  • フィールドはサポートされていません。Fields aren't supported.
  • 既定では、JSON のコメントまたは末尾のコンマによって例外がスローされます。By default, comments or trailing commas in the JSON throw exceptions. コメントと末尾のコンマを許可できます。You can allow comments and trailing commas.
  • 既定の最大の深さは64です。The default maximum depth is 64.

組み込みのコンバーターでサポートされていない機能を提供するために、カスタムコンバーターを実装することができます。You can implement custom converters to provide functionality that isn't supported by the built-in converters.

書式設定された JSON にシリアル化するSerialize to formatted JSON

JSON 出力を整形するには、JsonSerializerOptions.WriteIndentedtrueに設定します。To pretty-print the JSON output, set JsonSerializerOptions.WriteIndented to true:

var options = new JsonSerializerOptions
{
    WriteIndented = true,
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

シリアル化され、整形された JSON 出力の例を次に示します。Here's an example type to be serialized and pretty-printed JSON output:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot"
}

JSON の名前と値をカスタマイズするCustomize JSON names and values

既定では、プロパティ名とディクショナリキーは、大文字と小文字を含め、JSON の出力では変更されません。By default, property names and dictionary keys are unchanged in the JSON output, including case. 列挙値は数値として表されます。Enum values are represented as numbers. このセクションでは、次の方法について説明します。This section explains how to:

JSON プロパティの名前と値の特別な処理を必要とするその他のシナリオでは、カスタムコンバーターを実装できます。For other scenarios that require special handling of JSON property names and values, you can implement custom converters.

個々のプロパティ名をカスタマイズするCustomize individual property names

個々のプロパティの名前を設定するには、 [Jsonpropertyname]属性を使用します。To set the name of individual properties, use the [JsonPropertyName] attribute.

シリアル化し、結果として得られる JSON の例を次に示します。Here's an example type to serialize and resulting JSON:

public class WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "Wind": 35
}

この属性によって設定されるプロパティ名:The property name set by this attribute:

  • シリアル化と逆シリアル化の両方の方向で適用されます。Applies in both directions, for serialization and deserialization.
  • は、プロパティの名前付けポリシーよりも優先されます。Takes precedence over property naming policies.

すべての JSON プロパティ名にキャメルケースを使用するUse camel case for all JSON property names

すべての JSON プロパティ名にキャメルケースを使用するには、次の例に示すように、JsonSerializerOptions.PropertyNamingPolicyJsonNamingPolicy.CamelCaseに設定します。To use camel case for all JSON property names, set JsonSerializerOptions.PropertyNamingPolicy to JsonNamingPolicy.CamelCase, as shown in the following example:

var serializeOptions = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);

シリアル化と JSON 出力の例を次に示します。Here's an example class to serialize and JSON output:

public class WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
{
  "date": "2019-08-01T00:00:00-07:00",
  "temperatureCelsius": 25,
  "summary": "Hot",
  "Wind": 35
}

Camel 形式のプロパティの名前付けポリシー:The camel case property naming policy:

  • シリアル化および逆シリアル化に適用されます。Applies to serialization and deserialization.
  • [JsonPropertyName] 属性によってオーバーライドされます。Is overridden by [JsonPropertyName] attributes. このため、この例の JSON プロパティ名 Wind は camel 形式ではありません。This is why the JSON property name Wind in the example is not camel case.

カスタム JSON プロパティの名前付けポリシーを使用するUse a custom JSON property naming policy

カスタム JSON プロパティの名前付けポリシーを使用するには、次の例に示すように、JsonNamingPolicy から派生するクラスを作成し、ConvertName メソッドをオーバーライドします。To use a custom JSON property naming policy, create a class that derives from JsonNamingPolicy and override the ConvertName method, as shown in the following example:

using System.Text.Json;

namespace SystemTextJsonSamples
{
    public class UpperCaseNamingPolicy : JsonNamingPolicy
    {
        public override string ConvertName(string name) =>
            name.ToUpper();
    }
}

次に、[JsonSerializerOptions.PropertyNamingPolicy] プロパティを名前付けポリシークラスのインスタンスに設定します。Then set the JsonSerializerOptions.PropertyNamingPolicy property to an instance of your naming policy class:

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = new UpperCaseNamingPolicy(),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

シリアル化と JSON 出力の例を次に示します。Here's an example class to serialize and JSON output:

public class WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
{
  "DATE": "2019-08-01T00:00:00-07:00",
  "TEMPERATURECELSIUS": 25,
  "SUMMARY": "Hot",
  "Wind": 35
}

JSON プロパティの名前付けポリシー:The JSON property naming policy:

  • シリアル化および逆シリアル化に適用されます。Applies to serialization and deserialization.
  • [JsonPropertyName] 属性によってオーバーライドされます。Is overridden by [JsonPropertyName] attributes. このため、この例の JSON プロパティ名 Wind は大文字ではありません。This is why the JSON property name Wind in the example is not upper case.

Camel ケースディクショナリキーCamel case dictionary keys

シリアル化するオブジェクトのプロパティが Dictionary<string,TValue>型である場合は、string キーを camel 形式に変換できます。If a property of an object to be serialized is of type Dictionary<string,TValue>, the string keys can be converted to camel case. これを行うには、次の例に示すように、DictionaryKeyPolicyJsonNamingPolicy.CamelCaseに設定します。To do that, set DictionaryKeyPolicy to JsonNamingPolicy.CamelCase, as shown in the following example:

var options = new JsonSerializerOptions
{
    DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

キーと値の "ColdMinTemp", 20 ペアを持つ TemperatureRanges という名前のディクショナリを使用してオブジェクトをシリアル化すると "HotMinTemp", 40、次の例のように JSON 出力が生成されます。Serializing an object with a dictionary named TemperatureRanges that has key-value pairs "ColdMinTemp", 20 and "HotMinTemp", 40 would result in JSON output like the following example:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "TemperatureRanges": {
    "coldMinTemp": 20,
    "hotMinTemp": 40
  }
}

ディクショナリキーの camel ケースの名前付けポリシーは、シリアル化にのみ適用されます。The camel case naming policy for dictionary keys applies to serialization only. ディクショナリを逆シリアル化すると、DictionaryKeyPolicyJsonNamingPolicy.CamelCase を指定した場合でも、キーが JSON ファイルと一致します。If you deserialize a dictionary, the keys will match the JSON file even if you specify JsonNamingPolicy.CamelCase for the DictionaryKeyPolicy.

列挙 (文字列として)Enums as strings

既定では、列挙型は数値としてシリアル化されます。By default, enums are serialized as numbers. 列挙型名を文字列としてシリアル化するには、JsonStringEnumConverterを使用します。To serialize enum names as strings, use the JsonStringEnumConverter.

たとえば、列挙型を持つ次のクラスをシリアル化する必要があるとします。For example, suppose you need to serialize the following class that has an enum:

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

public enum Summary
{
    Cold, Cool, Warm, Hot
}

概要が Hotの場合、既定では、シリアル化された JSON の数値は3になります。If the Summary is Hot, by default the serialized JSON has the numeric value 3:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": 3
}

次のサンプルコードでは、数値ではなく列挙型名をシリアル化し、名前を camel 形式に変換します。The following sample code serializes the enum names instead of the numeric values, and converts the names to camel case:

options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
options.WriteIndented = true;
jsonString = JsonSerializer.Serialize(weatherForecast, options);

結果として得られる JSON は、次の例のようになります。The resulting JSON looks like the following example:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "hot"
}

列挙文字列名も、次の例に示すように逆シリアル化できます。Enum string names can be deserialized as well, as shown in the following example:

options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
weatherForecast = JsonSerializer.Deserialize<WeatherForecastWithEnum>(jsonString, options);

シリアル化からプロパティを除外するExclude properties from serialization

既定では、すべてのパブリックプロパティがシリアル化されます。By default, all public properties are serialized. 一部のオプションが JSON 出力に表示されないようにするには、いくつかのオプションがあります。If you don't want some of them to appear in the JSON output, you have several options. ここでは、を除外する方法について説明します。This section explains how to exclude:

個々のプロパティを除外するExclude individual properties

個々のプロパティを無視するには、 [Jsonignore]属性を使用します。To ignore individual properties, use the [JsonIgnore] attribute.

シリアル化する型と JSON 出力の例を次に示します。Here's an example type to serialize and JSON output:

public class WeatherForecastWithIgnoreAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    [JsonIgnore]
    public string Summary { get; set; }
}
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
}

すべての読み取り専用プロパティを除外するExclude all read-only properties

パブリックゲッターが含まれていてもパブリック setter がない場合、プロパティは読み取り専用です。A property is read-only if it contains a public getter but not a public setter. すべての読み取り専用プロパティを除外するには、次の例に示すように、JsonSerializerOptions.IgnoreReadOnlyPropertiestrueに設定します。To exclude all read-only properties, set the JsonSerializerOptions.IgnoreReadOnlyProperties to true, as shown in the following example:

var options = new JsonSerializerOptions
{
    IgnoreReadOnlyProperties = true,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

シリアル化する型と JSON 出力の例を次に示します。Here's an example type to serialize and JSON output:

public class WeatherForecastWithROProperty
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    public int WindSpeedReadOnly { get; private set; } = 35;
}
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
}

このオプションは、シリアル化にのみ適用されます。This option applies only to serialization. 逆シリアル化中、読み取り専用プロパティは既定では無視されます。During deserialization, read-only properties are ignored by default.

すべての null 値プロパティを除外するExclude all null value properties

すべての null 値プロパティを除外するには、次の例に示すように、IgnoreNullValues プロパティを trueに設定します。To exclude all null value properties, set the IgnoreNullValues property to true, as shown in the following example:

var options = new JsonSerializerOptions
{
    IgnoreNullValues = true,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

シリアル化し、JSON 出力を行うオブジェクトの例を次に示します。Here's an example object to serialize and JSON output:

propertyProperty ValueValue
日付Date 8/1/2019 12:00:00 AM-07:008/1/2019 12:00:00 AM -07:00
TemperatureCelsiusTemperatureCelsius 2525
要約Summary nullnull
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25
}

この設定は、シリアル化と逆シリアル化に適用されます。This setting applies to serialization and deserialization. 逆シリアル化に対する影響については、「逆シリアル化するときに null を無視する」を参照してください。For information about its effect on deserialization, see Ignore null when deserializing.

文字エンコードのカスタマイズCustomize character encoding

既定では、シリアライザーは ASCII 以外のすべての文字をエスケープします。By default, the serializer escapes all non-ASCII characters. つまり、xxxx が文字の Unicode コードである \uxxxx に置き換えます。That is, it replaces them with \uxxxx where xxxx is the Unicode code of the character. たとえば、Summary プロパティがキリルжаркоに設定されている場合、次の例に示すように WeatherForecast オブジェクトがシリアル化されます。For example, if the Summary property is set to Cyrillic жарко, the WeatherForecast object is serialized as shown in this example:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "\u0436\u0430\u0440\u043A\u043E"
}

言語文字セットのシリアル化Serialize language character sets

エスケープせずに1つ以上の言語の文字セットをシリアル化するには、次の例に示すように、System.Text.Encodings.Web.JavaScriptEncoderのインスタンスを作成するときにUnicode 範囲を指定します。To serialize the character set(s) of one or more languages without escaping, specify Unicode range(s) when creating an instance of System.Text.Encodings.Web.JavaScriptEncoder, as shown in the following example:

using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

このコードでは、キリル文字やギリシャ文字はエスケープされません。This code doesn't escape Cyrillic or Greek characters. Summary プロパティがキリルжаркоに設定されている場合、次の例に示すように WeatherForecast オブジェクトがシリアル化されます。If the Summary property is set to Cyrillic жарко, the WeatherForecast object is serialized as shown in this example:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "жарко"
}

エスケープせずにすべての言語セットをシリアル化するには、UnicodeRanges.Allを使用します。To serialize all language sets without escaping, use UnicodeRanges.All.

特定の文字のシリアル化Serialize specific characters

別の方法として、エスケープせずにを使用して許可する個々の文字を指定する方法もあります。An alternative is to specify individual characters that you want to allow through without being escaped. 次の例では、жаркоの最初の2つの文字のみをシリアル化します。The following example serializes only the first two characters of жарко:

using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
var encoderSettings = new TextEncoderSettings();
encoderSettings.AllowCharacters('\u0436', '\u0430');
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(encoderSettings),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

上記のコードによって生成される JSON の例を次に示します。Here's an example of JSON produced by the preceding code:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "жа\u0440\u043A\u043E"
}

すべての文字をシリアル化するSerialize all characters

エスケープを最小限に抑えるには、次の例に示すように JavaScriptEncoder.UnsafeRelaxedJsonEscapingを使用します。To minimize escaping you can use JavaScriptEncoder.UnsafeRelaxedJsonEscaping, as shown in the following example:

using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

注意事項

既定のエンコーダーと比較して、UnsafeRelaxedJsonEscaping エンコーダーでは、エスケープ解除された文字を通過できるようにすることが制限されています。Compared to the default encoder, the UnsafeRelaxedJsonEscaping encoder is more permissive about allowing characters to pass through unescaped:

  • <>&'など、HTML に依存する文字はエスケープされません。It doesn't escape HTML-sensitive characters such as <, >, &, and '.
  • XSS または情報漏えい攻撃 (クライアントとサーバーが文字セットに対して無効な場合に発生する可能性があります) に対する追加の多層防御は提供されません。It doesn't offer any additional defense-in-depth protections against XSS or information disclosure attacks, such as those which might result from the client and server disagreeing on the charset.

クライアントが結果のペイロードを UTF-8 でエンコードされた JSON として解釈することがわかっている場合にのみ、unsafe エンコーダーを使用します。Use the unsafe encoder only when it's known that the client will be interpreting the resulting payload as UTF-8 encoded JSON. たとえば、サーバーが応答ヘッダー Content-Type: application/json; charset=utf-8を送信している場合に使用できます。For example, you can use it if the server is sending the response header Content-Type: application/json; charset=utf-8. 未加工の UnsafeRelaxedJsonEscaping 出力が HTML ページまたは <script> 要素に出力されないようにします。Never allow the raw UnsafeRelaxedJsonEscaping output to be emitted into an HTML page or a <script> element.

派生クラスのプロパティのシリアル化Serialize properties of derived classes

ポリモーフィックな型階層のシリアル化はサポートされていません。Serialization of a polymorphic type hierarchy is not supported. たとえば、プロパティがインターフェイスまたは抽象クラスとして定義されている場合、ランタイム型に追加のプロパティがある場合でも、インターフェイスまたは抽象クラスで定義されたプロパティのみがシリアル化されます。For example, if a property is defined as an interface or an abstract class, only the properties defined on the interface or abstract class are serialized, even if the runtime type has additional properties. この動作の例外については、このセクションで説明します。The exceptions to this behavior are explained in this section.

たとえば、WeatherForecast クラスと派生クラス WeatherForecastDerivedがあるとします。For example, suppose you have a WeatherForecast class and a derived class WeatherForecastDerived:

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

また、コンパイル時に Serialize メソッドの型引数が WeatherForecastであるとします。And suppose the type argument of the Serialize method at compile time is WeatherForecast:

var options = new JsonSerializerOptions
{
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize<WeatherForecast>(weatherForecast, options);

このシナリオでは、weatherForecast オブジェクトが実際には WeatherForecastDerived オブジェクトであっても、WindSpeed プロパティはシリアル化されません。In this scenario, the WindSpeed property is not serialized even if the weatherForecast object is actually a WeatherForecastDerived object. 基本クラスのプロパティのみがシリアル化されます。Only the base class properties are serialized:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot"
}

この動作は、派生したランタイムによって作成された型でデータが誤って公開されるのを防ぐためのものです。This behavior is intended to help prevent accidental exposure of data in a derived runtime-created type.

前の例で派生型のプロパティをシリアル化するには、次のいずれかの方法を使用します。To serialize the properties of the derived type in the preceding example, use one of the following approaches:

  • 実行時に型を指定できるようにする Serialize のオーバーロードを呼び出します。Call an overload of Serialize that lets you specify the type at runtime:

    options = new JsonSerializerOptions
    {
        WriteIndented = true
    };
    jsonString = JsonSerializer.Serialize(weatherForecast, weatherForecast.GetType(), options);
    
  • objectとしてシリアル化するオブジェクトを宣言します。Declare the object to be serialized as object.

    options = new JsonSerializerOptions
    {
        WriteIndented = true
    };
    jsonString = JsonSerializer.Serialize<object>(weatherForecast, options);
    

前の例のシナリオでは、どちらの方法でも、WindSpeed プロパティが JSON 出力に含まれるようになっています。In the preceding example scenario, both approaches cause the WindSpeed property to be included in the JSON output:

{
  "WindSpeed": 35,
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot"
}

重要

これらの方法では、ルートオブジェクトのプロパティではなく、シリアル化するルートオブジェクトに対してのみ、ポリモーフィックなシリアル化が提供されます。These approaches provide polymorphic serialization only for the root object to be serialized, not for properties of that root object.

object型として定義すると、下位レベルのオブジェクトのポリモーフィックなシリアル化を取得できます。You can get polymorphic serialization for lower-level objects if you define them as type object. たとえば、WeatherForecast クラスに PreviousForecast という名前のプロパティがあり、WeatherForecast または object型として定義できるとします。For example, suppose your WeatherForecast class has a property named PreviousForecast that can be defined as type WeatherForecast or object:

public class WeatherForecastWithPrevious
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    public WeatherForecast PreviousForecast { get; set; }
}
public class WeatherForecastWithPreviousAsObject
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    public object PreviousForecast { get; set; }
}

PreviousForecast プロパティに WeatherForecastDerivedのインスタンスが含まれている場合は、次のようになります。If the PreviousForecast property contains an instance of WeatherForecastDerived:

  • WeatherForecastWithPrevious のシリアル化からの JSON 出力には WindSpeedが含まれていませんThe JSON output from serializing WeatherForecastWithPrevious doesn't include WindSpeed.
  • WeatherForecastWithPreviousAsObject をシリアル化するための JSON 出力には、WindSpeedが含まれています。The JSON output from serializing WeatherForecastWithPreviousAsObject includes WindSpeed.

WeatherForecastWithPreviousAsObjectをシリアル化するには、ルートオブジェクトが派生型である可能性のあるものではないため、Serialize<object> または GetType を呼び出す必要はありません。To serialize WeatherForecastWithPreviousAsObject, it isn't necessary to call Serialize<object> or GetType because the root object isn't the one that may be of a derived type. 次のコード例では、Serialize<object> または GetTypeを呼び出しません。The following code example doesn't call Serialize<object> or GetType:

options = new JsonSerializerOptions
{
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecastWithPreviousAsObject, options);

上記のコードは、WeatherForecastWithPreviousAsObjectを正しくシリアル化します。The preceding code correctly serializes WeatherForecastWithPreviousAsObject:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "PreviousForecast": {
    "WindSpeed": 35,
    "Date": "2019-08-01T00:00:00-07:00",
    "TemperatureCelsius": 25,
    "Summary": "Hot"
  }
}

object としてプロパティを定義するのと同じアプローチが、インターフェイスで動作します。The same approach of defining properties as object works with interfaces. 次のインターフェイスと実装があり、実装インスタンスを含むプロパティを使用してクラスをシリアル化するとします。Suppose you have the following interface and implementation, and you want to serialize a class with properties that contain implementation instances:

using System;

namespace SystemTextJsonSamples
{
    public interface IForecast
    {
        public DateTimeOffset Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string Summary { get; set; }
    }

    public class Forecast : IForecast
    {
        public DateTimeOffset Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string Summary { get; set; }
        public int WindSpeed { get; set; }
    }

    public class Forecasts
    {
        public IForecast Monday { get; set; }
        public object Tuesday { get; set; }
    }
}

Forecastsのインスタンスをシリアル化する場合、Tuesdayobjectとして定義されているので、Tuesday のみが WindSpeed プロパティを表示します。When you serialize an instance of Forecasts, only Tuesday shows the WindSpeed property, because Tuesday is defined as object:

var forecasts = new Forecasts
{
    Monday = new Forecast
    {
        Date = DateTime.Parse("2020-01-06"),
        TemperatureCelsius = 10,
        Summary = "Cool",
        WindSpeed = 8
    },
    Tuesday = new Forecast
    {
        Date = DateTime.Parse("2020-01-07"),
        TemperatureCelsius = 11,
        Summary = "Rainy",
        WindSpeed = 10
    }
};

options = new JsonSerializerOptions
{
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(forecasts, options);

次の例は、上記のコードの結果として得られる JSON を示しています。The following example shows the JSON that results from the preceding code:

{
  "Monday": {
    "Date": "2020-01-06T00:00:00-08:00",
    "TemperatureCelsius": 10,
    "Summary": "Cool"
  },
  "Tuesday": {
    "Date": "2020-01-07T00:00:00-08:00",
    "TemperatureCelsius": 11,
    "Summary": "Rainy",
    "WindSpeed": 10
  }
}

ポリモーフィックなシリアル化の詳細と、逆シリアル化の詳細については、「 Newtonsoft.Json から System.Text.Jsonに移行する方法」を参照してください。For more information about polymorphic serialization, and for information about deserialization, see How to migrate from Newtonsoft.Json to System.Text.Json.

コメントと末尾のコンマを許可するAllow comments and trailing commas

JSON では、コメントと末尾のコンマは既定で許可されていません。By default, comments and trailing commas are not allowed in JSON. JSON でコメントを許可するには、JsonSerializerOptions.ReadCommentHandling プロパティを JsonCommentHandling.Skipに設定します。To allow comments in the JSON, set the JsonSerializerOptions.ReadCommentHandling property to JsonCommentHandling.Skip. また、末尾のコンマを許可するには、JsonSerializerOptions.AllowTrailingCommas プロパティを trueに設定します。And to allow trailing commas, set the JsonSerializerOptions.AllowTrailingCommas property to true. 次の例では、両方を許可する方法を示します。The following example shows how to allow both:

var options = new JsonSerializerOptions
{
    ReadCommentHandling = JsonCommentHandling.Skip,
    AllowTrailingCommas = true,
};
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options);

次に、コメントと末尾のコンマを含む JSON の例を示します。Here's example JSON with comments and a trailing comma:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25, // Fahrenheit 77
  "Summary": "Hot", /* Zharko */
}

大文字と小文字を区別しないプロパティ照合Case-insensitive property matching

既定では、逆シリアル化では、JSON とターゲットオブジェクトのプロパティの間で大文字と小文字が区別されるプロパティ名の一致が検索されます。By default, deserialization looks for case-sensitive property name matches between JSON and the target object properties. この動作を変更するには、JsonSerializerOptions.PropertyNameCaseInsensitivetrueに設定します。To change that behavior, set JsonSerializerOptions.PropertyNameCaseInsensitive to true:

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
};
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options);

Camel 形式のプロパティ名を持つ JSON の例を次に示します。Here's example JSON with camel case property names. Pascal 形式のプロパティ名を持つ次の型に逆シリアル化できます。It can be deserialized into the following type that has Pascal case property names.

{
  "date": "2019-08-01T00:00:00-07:00",
  "temperatureCelsius": 25,
  "summary": "Hot",
}
public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}

Overflow JSON の処理Handle overflow JSON

逆シリアル化中に、対象の型のプロパティで表されないデータを JSON で受け取ることがあります。While deserializing, you might receive data in the JSON that is not represented by properties of the target type. たとえば、対象の型が次のようになっているとします。For example, suppose your target type is this:

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

逆シリアル化される JSON は次のとおりです。And the JSON to be deserialized is this:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "temperatureCelsius": 25,
  "Summary": "Hot",
  "DatesAvailable": [
    "2019-08-01T00:00:00-07:00",
    "2019-08-02T00:00:00-07:00"
  ],
  "SummaryWords": [
    "Cool",
    "Windy",
    "Humid"
  ]
}

示されている型に表示されている JSON を逆シリアル化すると、DatesAvailableSummaryWords のプロパティがなくなり、失われます。If you deserialize the JSON shown into the type shown, the DatesAvailable and SummaryWords properties have nowhere to go and are lost. これらのプロパティなどの追加データをキャプチャするには、 Jsonextensiondata属性を Dictionary<string,object> 型または Dictionary<string,JsonElement>型のプロパティに適用します。To capture extra data such as these properties, apply the JsonExtensionData attribute to a property of type Dictionary<string,object> or Dictionary<string,JsonElement>:

public class WeatherForecastWithExtensionData
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
    [JsonExtensionData]
    public Dictionary<string, object> ExtensionData { get; set; }
}

前に示した JSON をこのサンプル型に逆シリアル化すると、余分なデータが ExtensionData プロパティのキーと値のペアになります。When you deserialize the JSON shown earlier into this sample type, the extra data becomes key-value pairs of the ExtensionData property:

propertyProperty ValueValue メモNotes
日付Date 8/1/2019 12:00:00 AM-07:008/1/2019 12:00:00 AM -07:00
TemperatureCelsiusTemperatureCelsius 00 大文字と小文字が区別されない (JSON でtemperatureCelsius) ため、プロパティが設定されていません。Case-sensitive mismatch (temperatureCelsius in the JSON), so the property isn't set.
要約Summary Hot
ExtensionDataExtensionData temperatureCelsius:25temperatureCelsius: 25 大文字と小文字が一致しなかったため、この JSON プロパティは余分で、ディクショナリ内のキーと値のペアになります。Since the case didn't match, this JSON property is an extra and becomes a key-value pair in the dictionary.
使用可能な日:DatesAvailable:
8/1/2019 12:00:00 AM-07:008/1/2019 12:00:00 AM -07:00
8/2/2019 12:00:00 AM-07:008/2/2019 12:00:00 AM -07:00
JSON からの追加のプロパティはキーと値のペアになり、値オブジェクトとして配列が使用されます。Extra property from the JSON becomes a key-value pair, with an array as the value object.
概要語:SummaryWords:
CoolCool
強風Windy
HumidHumid
JSON からの追加のプロパティはキーと値のペアになり、値オブジェクトとして配列が使用されます。Extra property from the JSON becomes a key-value pair, with an array as the value object.

ターゲットオブジェクトがシリアル化されると、拡張データのキーと値のペアは、受信 JSON の場合と同様に JSON プロパティになります。When the target object is serialized, the extension data key value pairs become JSON properties just as they were in the incoming JSON:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 0,
  "Summary": "Hot",
  "temperatureCelsius": 25,
  "DatesAvailable": [
    "2019-08-01T00:00:00-07:00",
    "2019-08-02T00:00:00-07:00"
  ],
  "SummaryWords": [
    "Cool",
    "Windy",
    "Humid"
  ]
}

JSON には ExtensionData プロパティ名が表示されないことに注意してください。Notice that the ExtensionData property name doesn't appear in the JSON. この動作により、JSON は、逆シリアル化されない余分なデータを失うことなく、ラウンドトリップを行うことができます。This behavior lets the JSON make a round trip without losing any extra data that otherwise wouldn't be deserialized.

逆シリアル化時に null を無視するIgnore null when deserializing

既定では、JSON のプロパティが null の場合、対象オブジェクト内の対応するプロパティは null に設定されます。By default, if a property in JSON is null, the corresponding property in the target object is set to null. 場合によっては、ターゲットプロパティに既定値が設定されていて、null 値を使用して既定値をオーバーライドしないことがあります。In some scenarios, the target property might have a default value, and you don't want a null value to override the default.

たとえば、次のコードがターゲットオブジェクトを表しているとします。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:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": null
}

逆シリアル化後、WeatherForecastWithDefault オブジェクトの Summary プロパティは null になります。After deserialization, the Summary property of the WeatherForecastWithDefault object is null.

この動作を変更するには、次の例に示すように、JsonSerializerOptions.IgnoreNullValuestrueに設定します。To change this behavior, set JsonSerializerOptions.IgnoreNullValues to true, as shown in the following example:

var options = new JsonSerializerOptions
{
    IgnoreNullValues = true
};
weatherForecast = JsonSerializer.Deserialize<WeatherForecastWithDefault>(jsonString, options);

このオプションを使用すると、逆シリアル化後に、WeatherForecastWithDefault オブジェクトの Summary プロパティが既定値の "No summary" になります。With this option, the Summary property of the WeatherForecastWithDefault object is the default value "No summary" after deserialization.

JSON 内の Null 値は、有効な場合にのみ無視されます。Null values in the JSON are ignored only if they are valid. Null 非許容値型に対して Null 値を指定すると、例外が発生します。Null values for non-nullable value types cause exceptions.

Utf8JsonReader、Utf8JsonWriter、JsonDocumentUtf8JsonReader, Utf8JsonWriter, and JsonDocument

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. JsonSerializer.Deserialize メソッドは、内部で Utf8JsonReader を使用します。The JsonSerializer.Deserialize method uses Utf8JsonReader under the covers.

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. JsonSerializer.Serialize メソッドは、内部で Utf8JsonWriter を使用します。The JsonSerializer.Serialize method uses Utf8JsonWriter under the covers.

System.Text.Json.JsonDocument は、Utf8JsonReaderを使用して、読み取り専用ドキュメントオブジェクトモデル (DOM) を構築する機能を提供します。System.Text.Json.JsonDocument provides the ability to build a read-only Document Object Model (DOM) by using Utf8JsonReader. 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 array and object enumerators along with APIs to convert JSON text to common .NET types. JsonDocumentRootElement プロパティを公開します。JsonDocument exposes a RootElement property.

以下のセクションでは、これらのツールを使用して JSON の読み取りと書き込みを行う方法について説明します。The following sections show how to use these tools for reading and writing JSON.

データへのアクセスに JsonDocument を使用するUse JsonDocument for access to data

次の例は、JSON 文字列内のデータへのランダムアクセスに JsonDocument クラスを使用する方法を示しています。The following example shows how to use the JsonDocument class for random access to data in a JSON string:

double sum = 0;
int count = 0;

using (JsonDocument document = JsonDocument.Parse(jsonString))
{
    JsonElement root = document.RootElement;
    JsonElement studentsElement = root.GetProperty("Students");
    foreach (JsonElement student in studentsElement.EnumerateArray())
    {
        if (student.TryGetProperty("Grade", out JsonElement gradeElement))
        {
            sum += gradeElement.GetDouble();
        }
        else
        {
            sum += 70;
        }
        count++;
    }
}

double average = sum / count;
Console.WriteLine($"Average grade : {average}");

上のコードでは以下の操作が行われます。The preceding code:

  • は、分析する JSON が jsonStringという名前の文字列に含まれていると想定します。Assumes the JSON to analyze is in a string named jsonString.

  • Grade プロパティを持つ Students 配列内のオブジェクトの平均グレードを計算します。Calculates an average grade for objects in a Students array that have a Grade property.

  • 学年のない学生に対して既定のグレード70を割り当てます。Assigns a default grade of 70 for students who don't have a grade.

  • 各イテレーションで count 変数をインクリメントして生徒をカウントします。Counts students by incrementing a count variable with each iteration. 別の方法として、次の例に示すように GetArrayLengthを呼び出すこともできます。An alternative is to call GetArrayLength, as shown in the following example:

    double sum = 0;
    int count = 0;
    
    using (JsonDocument document = JsonDocument.Parse(jsonString))
    {
        JsonElement root = document.RootElement;
        JsonElement studentsElement = root.GetProperty("Students");
    
        count = studentsElement.GetArrayLength();
    
        foreach (JsonElement student in studentsElement.EnumerateArray())
        {
            if (student.TryGetProperty("Grade", out JsonElement gradeElement))
            {
                sum += gradeElement.GetDouble();
            }
            else
            {
                sum += 70;
            }
        }
    }
    
    double average = sum / count;
    Console.WriteLine($"Average grade : {average}");
    

このコードで処理される JSON の例を次に示します。Here's an example of the JSON that this code processes:

{
  "Class Name": "Science",
  "Teacher\u0027s Name": "Jane",
  "Semester": "2019-01-01",
  "Students": [
    {
      "Name": "John",
      "Grade": 94.3
    },
    {
      "Name": "James",
      "Grade": 81.0
    },
    {
      "Name": "Julia",
      "Grade": 91.9
    },
    {
      "Name": "Jessica",
      "Grade": 72.4
    },
    {
      "Name": "Johnathan"
    }
  ],
  "Final": true
}

JsonDocument を使用した JSON の記述Use JsonDocument to write JSON

次の例は、JsonDocumentから JSON を書き込む方法を示しています。The following example shows how to write JSON from a JsonDocument:

string jsonString = File.ReadAllText(inputFileName);

var writerOptions = new JsonWriterOptions
{
    Indented = true
};

var documentOptions = new JsonDocumentOptions
{
    CommentHandling = JsonCommentHandling.Skip
};

using FileStream fs = File.Create(outputFileName);
using var writer = new Utf8JsonWriter(fs, options: writerOptions);
using JsonDocument document = JsonDocument.Parse(jsonString, documentOptions);

JsonElement root = document.RootElement;

if (root.ValueKind == JsonValueKind.Object)
{
    writer.WriteStartObject();
}
else
{
    return;
}

foreach (JsonProperty property in root.EnumerateObject())
{
    property.WriteTo(writer);
}

writer.WriteEndObject();

writer.Flush();

上のコードでは以下の操作が行われます。The preceding code:

  • JSON ファイルを読み取り、データを JsonDocumentに読み込み、書式設定された (非常に印刷された) JSON をファイルに書き込みます。Reads a JSON file, loads the data into a JsonDocument, and writes formatted (pretty-printed) JSON to a file.
  • JsonDocumentOptions を使用して、入力 JSON 内のコメントを許可しますが、無視することを指定します。Uses JsonDocumentOptions to specify that comments in the input JSON are allowed but ignored.
  • 完了すると、はライターで Flush を呼び出します。When finished, calls Flush on the writer. 別の方法として、破棄されたときにライターを autoflush することもできます。An alternative is to let the writer autoflush when it's disposed.

コード例によって処理される JSON 入力の例を次に示します。Here's an example of JSON input to be processed by the example code:

{"Class Name": "Science","Teacher's Name": "Jane","Semester": "2019-01-01","Students": [{"Name": "John","Grade": 94.3},{"Name": "James","Grade": 81.0},{"Name": "Julia","Grade": 91.9},{"Name": "Jessica","Grade": 72.4},{"Name": "Johnathan"}],"Final": true}

その結果、次のような整形出力の JSON 出力が生成されます。The result is the following pretty-printed JSON output:

{
  "Class Name": "Science",
  "Teacher\u0027s Name": "Jane",
  "Semester": "2019-01-01",
  "Students": [
    {
      "Name": "John",
      "Grade": 94.3
    },
    {
      "Name": "James",
      "Grade": 81.0
    },
    {
      "Name": "Julia",
      "Grade": 91.9
    },
    {
      "Name": "Jessica",
      "Grade": 72.4
    },
    {
      "Name": "Johnathan"
    }
  ],
  "Final": true
}

Utf8JsonWriter を使用するUse Utf8JsonWriter

次の例は、Utf8JsonWriter クラスの使用方法を示しています。The following example shows how to use the Utf8JsonWriter class:

var options = new JsonWriterOptions
{
    Indented = true
};

using (var stream = new MemoryStream())
{
    using (var writer = new Utf8JsonWriter(stream, options))
    {
        writer.WriteStartObject();
        writer.WriteString("date", DateTimeOffset.UtcNow);
        writer.WriteNumber("temp", 42);
        writer.WriteEndObject();
    }

    string json = Encoding.UTF8.GetString(stream.ToArray());
    Console.WriteLine(json);
}

Utf8JsonReader を使用するUse Utf8JsonReader

次の例は、Utf8JsonReader クラスの使用方法を示しています。The following example shows how to use the Utf8JsonReader class:

var options = new JsonReaderOptions
{
    AllowTrailingCommas = true,
    CommentHandling = JsonCommentHandling.Skip
};
Utf8JsonReader reader = new Utf8JsonReader(jsonUtf8Bytes, options);

while (reader.Read())
{
    Console.Write(reader.TokenType);

    switch (reader.TokenType)
    {
        case JsonTokenType.PropertyName:
        case JsonTokenType.String:
            {
                string text = reader.GetString();
                Console.Write(" ");
                Console.Write(text);
                break;
            }

        case JsonTokenType.Number:
            {
                int intValue = reader.GetInt32();
                Console.Write(" ");
                Console.Write(intValue);
                break;
            }

            // Other token types elided for brevity
    }
    Console.WriteLine();
}

上記のコードでは、jsonUtf8 変数が、UTF-8 としてエンコードされた有効な JSON を含むバイト配列であることを前提としています。The preceding code assumes that the jsonUtf8 variable is a byte array that contains valid JSON, encoded as UTF-8.

Utf8JsonReader を使用してデータをフィルター処理するFilter data using Utf8JsonReader

次の例は、ファイルを同期的に読み取り、値を検索する方法を示しています。The following example shows how to read a file synchronously and search for a value:

using System;
using System.IO;
using System.Text;
using System.Text.Json;

namespace SystemTextJsonSamples
{
    public class Utf8ReaderFromFile
    {
        private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
        private static ReadOnlySpan<byte> Utf8Bom => new byte[] { 0xEF, 0xBB, 0xBF };
        public static void Run()
        {
            // ReadAllBytes if the file encoding is UTF-8:
            string fileName = "UniversitiesUtf8.json";
            ReadOnlySpan<byte> jsonReadOnlySpan = File.ReadAllBytes(fileName);

            // Read past the UTF-8 BOM bytes if a BOM exists.
            if (jsonReadOnlySpan.StartsWith(Utf8Bom))
            {
                jsonReadOnlySpan = jsonReadOnlySpan.Slice(Utf8Bom.Length);
            }

            // Or read as UTF-16 and transcode to UTF-8 to convert to a ReadOnlySpan<byte>
            //string fileName = "Universities.json";
            //string jsonString = File.ReadAllText(fileName);
            //ReadOnlySpan<byte> jsonReadOnlySpan = Encoding.UTF8.GetBytes(jsonString);


            int count = 0;
            int total = 0;

            var reader = new Utf8JsonReader(jsonReadOnlySpan);

            while (reader.Read())
            {
                JsonTokenType tokenType = reader.TokenType;

                switch (tokenType)
                {
                    case JsonTokenType.StartObject:
                        total++;
                        break;
                    case JsonTokenType.PropertyName:
                        if (reader.ValueTextEquals(s_nameUtf8))
                        {
                            // Assume valid JSON, known schema
                            reader.Read();
                            if (reader.GetString().EndsWith("University"))
                            {
                                count++;
                            }
                        }
                        break;
                }
            }
            Console.WriteLine($"{count} out of {total} have names that end with 'University'");
        }
    }
}

上のコードでは以下の操作が行われます。The preceding code:

  • JSON にオブジェクトの配列が含まれており、各オブジェクトに文字列型の "name" プロパティが含まれていると仮定します。Assumes the JSON contains an array of objects and each object may contain a "name" property of type string.

  • "大学" で終わるオブジェクトと "name" プロパティ値をカウントします。Counts objects and "name" property values that end with "University".

  • は、ファイルが UTF-16 としてエンコードされているものと想定し、UTF-8 にトランスコードします。Assumes the file is encoded as UTF-16 and transcodes it into UTF-8. UTF-8 としてエンコードされたファイルは、次のコードを使用して、ReadOnlySpan<byte>に直接読み取ることができます。A file encoded as UTF-8 can be read directly into a ReadOnlySpan<byte>, by using the following code:

    ReadOnlySpan<byte> jsonReadOnlySpan = File.ReadAllBytes(fileName); 
    

    ファイルに UTF-8 バイト順マーク (BOM) が含まれている場合は、リーダーがテキストを受け取るため、バイトを Utf8JsonReaderに渡す前に削除します。If the file contains a UTF-8 byte order mark (BOM), remove it before passing the bytes to the Utf8JsonReader, since the reader expects text. それ以外の場合、BOM は無効な JSON と見なされ、リーダーは例外をスローします。Otherwise, the BOM is considered invalid JSON, and the reader throws an exception.

上記のコードが読み取ることができる JSON のサンプルを次に示します。Here's a JSON sample that the preceding code can read. 結果として生成される概要メッセージは、"2 ~ 4 個の名前が ' 大学 ' で終わっています" です。The resulting summary message is "2 out of 4 have names that end with 'University'":

[
  {
    "web_pages": [ "https://contoso.edu/" ],
    "alpha_two_code": "US",
    "state-province": null,
    "country": "United States",
    "domains": [ "contoso.edu" ],
    "name": "Contoso Community College"
  },
  {
    "web_pages": [ "http://fabrikam.edu/" ],
    "alpha_two_code": "US",
    "state-province": null,
    "country": "United States",
    "domains": [ "fabrikam.edu" ],
    "name": "Fabrikam Community College"
  },
  {
    "web_pages": [ "http://www.contosouniversity.edu/" ],
    "alpha_two_code": "US",
    "state-province": null,
    "country": "United States",
    "domains": [ "contosouniversity.edu" ],
    "name": "Contoso University"
  },
  {
    "web_pages": [ "http://www.fabrikamuniversity.edu/" ],
    "alpha_two_code": "US",
    "state-province": null,
    "country": "United States",
    "domains": [ "fabrikamuniversity.edu" ],
    "name": "Fabrikam University"
  }
]

その他の技術情報Additional resources