Share via


如何使用 System.Text.Json 自訂屬性名稱與值

根據預設,JSON 輸出中的屬性名稱和字典索引鍵會保持不變 (包括大小寫)。 列舉值會以數字表示。 屬性會依其定義的順序進行序列化。 不過,您可以透過下列方式自訂這些行為:

  • 指定特定的序列化屬性名稱。
  • 針對屬性名稱和字典索引鍵,使用內建命名原則,例如駝峰式大小寫、蛇式大小寫或肉串式大小寫。
  • 針對屬性名稱和字典索引鍵使用自訂命名原則。
  • 使用或不使用命名原則,將列舉值序列化為字串。
  • 設定序列化屬性的順序。

注意

Web 預設命名原則為駝峰式大小寫。

對於需要特殊處理 JSON 屬性名稱和值的其他案例,您可以實作自訂轉換器

自訂個別屬性名稱

如果要設定個別屬性 (Property) 的名稱,請使用 [JsonPropertyName] 屬性 (Attribute)。

以下是要序列化的範例類型與產生的 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
}

此屬性 (Attribute) 所設定的屬性 (Property) 名稱:

使用內建命名原則

下表顯示內建命名原則,及其如何影響屬性名稱。

命名原則 描述 原始屬性名稱 轉換的屬性名稱
CamelCase 第一個單字會以小寫字元開頭。
後續單字會以大寫字元開頭。
TempCelsius tempCelsius
KebabCaseLower* 單字會以連字號分隔。
所有字元都是小寫。
TempCelsius temp-celsius
KebabCaseUpper* 單字會以連字號分隔。
所有字元都是大寫。
TempCelsius TEMP-CELSIUS
SnakeCaseLower* 單字會以底線分隔。
所有字元都是小寫。
TempCelsius temp_celsius
SnakeCaseUpper* 單字會以底線分隔。
所有字元都是大寫。
TempCelsius TEMP_CELSIUS

* 在 .NET 8 版和更新版本中可供使用。

下列範例示範如何藉由將 JsonSerializerOptions.PropertyNamingPolicy 設定為 JsonNamingPolicy.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 不是駝峰式大小寫的原因。

注意

內建命名原則皆不支援代理字組的字母。 如需詳細資訊,請參閱 dotnet/執行階段問題 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 檔案。

以字串表示列舉

根據預設,會將列舉序列化為數字。 若要將列舉名稱序列化為字串,請使用 JsonStringEnumConverterJsonStringEnumConverter<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

如果摘要是 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] 屬性 (Attribute) 可讓您在序列化期間,指定 JSON 輸出中的屬性 (Property) 順序。 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"
//}

另請參閱