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

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

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

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
}

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

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

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

名前付けポリシー 説明 元のプロパティ名 変換されたプロパティ名
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 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 はキャメル ケースではありません。

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 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 キーは、キャメル ケースなどの名前付けポリシーを使用して変換できます。 これを行うには、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"
//}

関連項目