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

既定では、プロパティ名とディクショナリ キーは、大文字と小文字の区別を含め、JSON の出力では変更されません。 列挙型の値は数値として表されます。 この記事では、次の方法について学習します。

Note

Web の既定値はキャメル ケースです。

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

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

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

シリアル化する型と、結果として得られる 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; }
}
Public Class WeatherForecastWithPropertyNameAttribute
    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 プロパティ名にキャメル ケースを使用する

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

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 WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyNameAttribute
    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 はキャメル ケースではありません。

カスタム 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 WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyNameAttribute
    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 キーをキャメル ケースに変換できます。 これを行うには、次の例に示すように、DictionaryKeyPolicyJsonNamingPolicy.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
  }
}

ディクショナリ キーに対するキャメル ケースの名前付けポリシーは、シリアル化にのみ適用されます。 ディクショナリを逆シリアル化すると、DictionaryKeyPolicyJsonNamingPolicy.CamelCase を指定した場合でも、キーが JSON ファイルと一致します。

文字列としての列挙型

既定では、列挙型は数値としてシリアル化されます。 列挙型名を文字列としてシリアル化するには、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 名前付けポリシーが指定されていても機能します。 その他の名前付けポリシー (スネーク ケースなど) はサポートされていません。 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)

スネーク ケース名前付けポリシーを使用しながら逆シリアル化をサポートするカスタム コンバーター コードについては、「列挙型文字列値の逆シリアル化をサポートする」を参照してください。

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

[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"
//}

関連項目