System.Text.Json でプロパティの名前と値をカスタマイズする方法

既定では、プロパティ名とディクショナリ キーは、大文字と小文字の区別を含め、JSON の出力では変更されません。 列挙型の値は数値として表されます。 また、プロパティは定義された順序でシリアル化されます。 ただし、次の方法でこれらの動作をカスタマイズできます:

  • 特定のシリアル化されたプロパティ名の指定。
  • camelCase、snake_case、kebab-case などの組み込みの 名前付けポリシーを使用して、プロパティ名とディクショナリ キーを使用します。
  • プロパティ名とディクショナリ キーにカスタム名前付けポリシーを使用する。
  • 名前付けポリシーの有無にかかわらず、列挙型の値を文字列としてシリアル化する。
  • シリアル化されたプロパティの順序の構成。

Note

Web の既定 の名前付けポリシーはキャメル ケースです。

ヒント

GitHub Copilot では、AI の支援を使用してプロパティの名前と値をカスタマイズできます。

JSON プロパティの名前と値の特別な処理を必要とするその他のシナリオでは、カスタム コンバーターを実装することができます。

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

個々のプロパティの名前を設定するには、[JsonPropertyName] 属性を使用します。

シリアル化する型と、結果として得られる JSON の例を次に示します。

public class WeatherForecastWithPropertyName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyName
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String

    <JsonPropertyName("Wind")>
    Public Property WindSpeed As Integer

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

この属性によって設定されるプロパティ名は:

組み込みの名前付けポリシーを使用する

次の表に、組み込みの名前付けポリシーと、それらがプロパティ名にどのように影響するかを示します。

名前付けポリシー 説明 元のプロパティ名 変換されたプロパティ名
CamelCase 最初の単語は小文字で始まります。
連続する単語は大文字で始まります。
TempCelsius tempCelsius
KebabCaseLower* 単語はハイフンで区切られます。
すべての文字は小文字です。
TempCelsius temp-celsius
KebabCaseUpper* 単語はハイフンで区切られます。
すべての文字は大文字です。
TempCelsius TEMP-CELSIUS
SnakeCaseLower* 単語はアンダースコアで区切ります。
すべての文字は小文字です。
TempCelsius temp_celsius
SnakeCaseUpper* 単語はアンダースコアで区切ります。
すべての文字は大文字です。
TempCelsius TEMP_CELSIUS

* .NET 8 以降のバージョンで使用できます。

次の例では、 JsonSerializerOptions.PropertyNamingPolicyJsonNamingPolicy.CamelCaseに設定して、すべての JSON プロパティ名にキャメル ケースを使用する方法を示します:

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

シリアル化するクラスと JSON 出力の例を次に示します。

public class WeatherForecastWithPropertyName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyName
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String

    <JsonPropertyName("Wind")>
    Public Property WindSpeed As Integer

End Class
{
  "date": "2019-08-01T00:00:00-07:00",
  "temperatureCelsius": 25,
  "summary": "Hot",
  "Wind": 35
}

名前付けポリシー:

  • シリアル化と逆シリアル化に適用されます。
  • [JsonPropertyName] 属性によってオーバーライドされます。 このため、この例の JSON プロパティ名 Wind はキャメル ケースではありません。

Note

組み込みの名前付けポリシーでは、サロゲート ペアである文字はサポートされていません。 詳細については、dotnet/runtime issue 90352 を参照してください。

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

カスタム JSON プロパティの名前付けポリシーを使用するには、次の例に示すように、JsonNamingPolicy から派生するクラスを作成し、ConvertName メソッドをオーバーライドします。

using System.Text.Json;

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

Namespace SystemTextJsonSamples

    Public Class UpperCaseNamingPolicy
        Inherits JsonNamingPolicy

        Public Overrides Function ConvertName(name As String) As String
            Return name.ToUpper()
        End Function

    End Class

End Namespace

次に、JsonSerializerOptions.PropertyNamingPolicy プロパティを名前付けポリシー クラスのインスタンスに設定します。

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = new UpperCaseNamingPolicy(),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
Dim options As JsonSerializerOptions = New JsonSerializerOptions With {
    .PropertyNamingPolicy = New UpperCaseNamingPolicy,
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)

シリアル化するクラスと JSON 出力の例を次に示します。

public class WeatherForecastWithPropertyName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyName
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String

    <JsonPropertyName("Wind")>
    Public Property WindSpeed As Integer

End Class
{
  "DATE": "2019-08-01T00:00:00-07:00",
  "TEMPERATURECELSIUS": 25,
  "SUMMARY": "Hot",
  "Wind": 35
}

JSON プロパティの名前付けポリシーは:

  • シリアル化と逆シリアル化に適用されます。
  • [JsonPropertyName] 属性によってオーバーライドされます。 このため、この例の JSON プロパティ名 Wind は大文字ではありません。

ディクショナリ キーに名前付けポリシーを使用する

シリアル化するオブジェクトのプロパティが Dictionary<string,TValue> 型の場合、string キーは、キャメル ケースなどの名前付けポリシーを使用して変換できます。 これを行うには、JsonSerializerOptions.DictionaryKeyPolicy を目的の名前付けポリシーに設定します。 次の例では、CamelCase 名前付けポリシーを使用します:

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

キーと値のペア "ColdMinTemp", 20 および "HotMinTemp", 40 を持つ TemperatureRanges という名前のディクショナリを使用してオブジェクトをシリアル化すると、次の例のような JSON 出力が生成されます。

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

ディクショナリ キーの名前付けポリシーは、シリアル化にのみ適用されます。 ディクショナリを逆シリアル化すると、既定以外の名前付けポリシーに JsonSerializerOptions.DictionaryKeyPolicy 設定した場合でも、キーは JSON ファイルと一致します。

文字列としての列挙型

既定では、列挙型は数値としてシリアル化されます。 列挙型名を文字列としてシリアル化するには、JsonStringEnumConverter または JsonStringEnumConverter<TEnum> コンバーターを使用します。 ネイティブ AOT ランタイムでは、 JsonStringEnumConverter<TEnum> のみがサポートされます。

既定では、列挙型は数値としてシリアル化されます。 列挙型名を文字列としてシリアル化するには、 JsonStringEnumConverter コンバーターを使用します。

たとえば、列挙型を持つ次のクラスをシリアル化する必要があるとします。

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
}
Public Class WeatherForecastWithEnum
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As Summary
End Class

Public Enum Summary
    Cold
    Cool
    Warm
    Hot
End Enum

Summary が Hot の場合、既定では、シリアル化された JSON には数値 3 があります。

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

次のサンプル コードでは、数値ではなく列挙型名をシリアル化し、名前をキャメル ケースに変換します。

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

結果として生成される JSON は、次の例のようになります。

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

組み込みの JsonStringEnumConverter では、文字列値も逆シリアル化できます。 これは、指定された名前付けポリシーの有無にかかわらず機能します。 CamelCase を使用した逆シリアル化の例を次に示します。

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

JsonConverterAttribute を使用して列挙型に注釈を付けることで、使用するコンバーターを指定することもできます。 次の例は、 JsonConverterAttribute 属性を使用して JsonStringEnumConverter<TEnum> (.NET 8 以降のバージョンで使用可能) を指定する方法を示しています。 たとえば、列挙型を持つ次のクラスをシリアル化する必要があるとします。

public class WeatherForecastWithPrecipEnum
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public Precipitation? Precipitation { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter<Precipitation>))]
public enum Precipitation
{
    Drizzle, Rain, Sleet, Hail, Snow
}

次のサンプル コードでは、数値の代わりに列挙型名をシリアル化します:

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

結果として生成される JSON は、次の例のようになります。

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Precipitation": "Sleet"
}

ソース生成でコンバーターを使用するには、「列挙型フィールドを文字列としてシリアル化する」を参照してください。

シリアル化されるプロパティの順序を構成する

既定では、プロパティはクラスで定義されている順序でシリアル化されます。 [JsonPropertyOrder] 属性では、シリアル化から出力された JSON のプロパティの順序を指定できます。 Order プロパティの既定値はゼロです。 Order を正数に設定すると、既定値を持つものの後にプロパティが配置されます。 負の Order の場合、既定値を持つものの前にプロパティが配置されます。 プロパティは、Order 値が最も低いものから最も高いものへの順で書き込まれます。 次に例を示します。

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

namespace PropertyOrder
{
    public class WeatherForecast
    {
        [JsonPropertyOrder(-5)]
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        [JsonPropertyOrder(-2)]
        public int TemperatureF { get; set; }
        [JsonPropertyOrder(5)]
        public string? Summary { get; set; }
        [JsonPropertyOrder(2)]
        public int WindSpeed { get; set; }
    }

    public class Program
    {
        public static void Main()
        {
            var weatherForecast = new WeatherForecast
            {
                Date = DateTime.Parse("2019-08-01"),
                TemperatureC = 25,
                TemperatureF = 25,
                Summary = "Hot",
                WindSpeed = 10
            };

            var options = new JsonSerializerOptions { WriteIndented = true };
            string jsonString = JsonSerializer.Serialize(weatherForecast, options);
            Console.WriteLine(jsonString);
        }
    }
}
// output:
//{
//  "Date": "2019-08-01T00:00:00",
//  "TemperatureF": 25,
//  "TemperatureC": 25,
//  "WindSpeed": 10,
//  "Summary": "Hot"
//}

Github Copilot を使用してプロパティの名前と順序をカスタマイズする

IDE で GitHub Copilot を使用すると、シリアル化されたプロパティの名前と順序をカスタマイズしたコードを生成できます。

Visual Studio 2022 バージョン 17.8 以降を使用している場合は、System.Text.Json によるシリアル化での JSON 出力におけるプロパティの名前と順序をカスタマイズしたコードの生成に、Visual Studio の AI 駆動型 GitHub Copilot を試すことができます。 次の例のように、Copilot チャット ウィンドウにプロンプ​​トとして質問を送信します。 エディター ウィンドウ自体で インライン チャット を使用してプロンプトを送信することもできます。

Note

GitHub Copilot では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 生成されたコードまたは提案を必ず確認してください。 GitHub Copilot の一般的な用途、製品への影響、人間の監視、プライバシーの詳細については、 GitHub Copilot に関する FAQを参照してください。

次の例は、Copilot を使用して既存のコードを変更し、JSON にシリアル化するときにプロパティの名前と順序をカスタマイズする方法を示しています。

  1. エディターで、次の C# サンプル コードをコード ファイル Example.cs に追加します。 Visual Studio では、C# コンソール アプリケーション プロジェクトを使用して、この例を試すことができます。

    using System.Text.Json;
    
    public class Person
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public int Age { get; set; }
        public string? Country { get; set; }
    }
    
    public class Program
    {
        public static void Main()
        {
            var person = new Person
            {
                FirstName = "John",
                LastName = "Doe",
                Age = 30,
                Country = "USA"
            };
    
            string jsonString = JsonSerializer.Serialize(person);
            Console.WriteLine(jsonString);
        }
    }
    

    Example.cs コードは次のことを行います。

    • Person クラスのインスタンスを作成し、各プロパティをそれぞれの値で初期化します。
    • JsonSerializer.Serialize を使用して、person オブジェクトを JSON 文字列にシリアル化します。
    • 以下の JSON 文字列をコンソールに出力します。
    {"FirstName":"John","LastName":"Doe","Age":30,"Country":"USA"}
    
  2. Copilot Chat で次のプロンプトを入力してコードを変更し、JSON シリアル化出力の名前と順序をカスタマイズします。

    #Example.cs のコードを変更し、System.Text.Json を使用してシリアル化での JSON 出力におけるプロパティの名前と順序をカスタマイズしてください。 プロパティ名 FirstName を first_name、LastName を last_name に設定してください。 Country、FirstName、LastName、Age の順序に設定してください。 カスタマイズされたシリアル化出力を提供してください。

    プロンプト内の #Example.cs は、Copilot へのコンテキストとしてファイル参照を提供します。 このプロンプトをカスタマイズすると、要件に合ったプロパティ名と値を含む JSON 文字列を出力できます。 スコープ指定されたコンテキストでインテントを設定してより適切な回答を得るには、スラッシュ コマンド、ファイル/メソッド/クラスへの参照、スレッドなどのチャット機能を使用できます。

    次の出力は、Copilot Chat の応答の例を示しています。

    To customize the property names and order of the JSON output using System.Text.Json, you can use the JsonPropertyName attribute to rename properties and the JsonPropertyOrder attribute to set the order. Here's how you can modify your code:
    
    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    public class Person
    {
        [JsonPropertyName("first_name")]
        [JsonPropertyOrder(2)]
        public string? FirstName { get; set; }
    
        [JsonPropertyName("last_name")]
        [JsonPropertyOrder(3)]
        public string? LastName { get; set; }
    
        [JsonPropertyOrder(4)]
        public int Age { get; set; }
    
        [JsonPropertyOrder(1)]
        public string? Country { get; set; }
    }
    
    public class Program
    {
        public static void Main()
        {
            var person = new Person
            {
                FirstName = "John",
                LastName = "Doe",
                Age = 30,
                Country = "USA"
            };
    
            string jsonString = JsonSerializer.Serialize(person, new JsonSerializerOptions { WriteIndented = true });
            Console.WriteLine(jsonString);
        }
    }
    
    **Explanation:**
    
    1. Renaming Properties: The JsonPropertyName attribute is used to rename FirstName to first_name and LastName to last_name.
    2. Ordering Properties: The JsonPropertyOrder attribute is used to set the order of the properties in the JSON output. The order is set as:
       • Country (Order 1)
       • FirstName (Order 2)
       • LastName (Order 3)
       • Age (Order 4)
    3. Indented JSON: The JsonSerializerOptions with WriteIndented = true is used to make the JSON output more readable.
    
    **Customized Serialization Output:**
    {
      "Country": "USA",
      "first_name": "John",
      "last_name": "Doe",
      "Age": 30
    }
    
    This ensures that the JSON output has the customized property names and the specified order.
    

Copilot がコード ブロックを返す場合、応答には、コードをコピーする、コードを新しいファイルに挿入する、またはコード出力をプレビューするオプションが含まれます。

Note

結果は、サンプルの回答に示されているものと異なる場合があります。 AI モデルは非決定論的です。つまり、同じ質問を受けたときに異なる応答を返す場合があります。 これは、時間の経過に伴う学習と適応の進行、言語バリエーション、チャット履歴などのコンテキストの変更などが原因である可能性があります。

関連項目