共用方式為


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

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

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

注意

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

提示

您可以使用 AI 輔助來透過 GitHub Copilot 自訂屬性名稱和值

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

自訂個別屬性名稱

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

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

此屬性 (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 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 不是駝峰式大小寫的原因。

注意

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

以字串表示列舉

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

使用 Github Copilot 自訂屬性名稱和順序

您可以在 IDE 中使用 GitHub Copilot 產生程式碼,以自訂序列化屬性的名稱和順序。

如果您使用的是 Visual Studio 2022 版本 17.8 或更新版本,您可以嘗試在 Visual Studio 中使用由 AI 驅動的 GitHub Copilot 產生程式碼,以使用 System.Text.Json 在序列化的 JSON 輸出中自訂屬性名稱和順序。 在 Copilot 聊天視窗中將您的問題當成提示提交,如以下範例。 您也可以在編輯器視窗本身使用內嵌聊天來提交提示。

注意

GitHub Copilot 是由 AI 驅動的,因此可能會有意外和錯誤的情況發生。 任何生成的代碼或建議都務必要驗證。 有關 GitHub Copilot 的一般使用、產品影響、人為監督和隱私權的更多資訊,請參閱 [GitHub Copilot 常見問題解答]

下列範例示範如何使用 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.Serializeperson 物件序列化為 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 字串。 若要設定意圖並取得範圍內容更好的解答,您可以使用聊天功能,例如 Slash 命令、檔案的參考、方法或類別以及執行緒

    下列輸出顯示 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 傳回程式碼區塊時,回應會包含複製程式碼、將程式碼插入新檔案或預覽程式碼輸出的選項。

注意

您的結果可能會與範例回應中顯示的內容不同。 AI 模型不具決定性,這代表在詢問相同問題時,它們可能會傳回不同的回答。 這可能是由於隨著時間而進行的額外學習和調整、語言變化、上下文變化 (例如您的聊天記錄) 等因素造成的。

另請參閱