【C# 序列化】 自定義Json轉換器模式


【C# 序列化】 自定義Json轉換器

https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-6-0

Json轉換器簡介

本文介紹如何為 System.Text.Json 命名空間中提供的 JSON 序列化類創建自定義轉換器。

轉換器是一種將對象或值與 JSON 相互轉換的類。 System.Text.Json 命名空間為映射到 JavaScript 基元的大多數基元類型提供內置轉換器。 可以編寫自定義轉換器來實現以下目標:

  • 重寫內置轉換器的默認行為。 例如,你可能希望通過 mm/dd/yyyy 格式來表示 DateTime 值。 默認情況下,支持 ISO 8601-1:2019,包括 RFC 3339 配置文件。 有關詳細信息,請參閱 中的 DateTime 和 DateTimeOffset 支持。
  • 支持自定義值類型。 例如,PhoneNumber 結構。

還可以編寫自定義轉換器,以使用當前版本中未包含的功能自定義或擴展 System.Text.Json。 本文后面部分介紹了以下方案:

自定義轉換器模式(基本模式和工廠模式)

用於創建自定義轉換器的模式有兩種:基本模式和工廠模式。 工廠模式適用於處理類型 Enum 或開放式泛型的轉換器。 基本模式適用於非泛型或封閉式泛型類型。 例如,適用於以下類型的轉換器需要工廠模式:

可以通過基本模式處理的類型的一些示例包括:

  • Dictionary<int, string>
  • WeekdaysEnum
  • List<DateTimeOffset>
  • DateTime
  • Int32

基本模式創建的類可以處理一種類型。 工廠模式創建的類在運行時確定所需的特定類型,並動態創建適當的轉換器。

自定義基本模式轉換器

遵循基本模式的步驟

以下步驟說明如何遵循基本模式來創建轉換器:

  • 創建一個派生自 JsonConverter<T> 的類,其中 T 是要進行序列化和反序列化的類型。
  • 重寫 Read 方法,以反序列化傳入 JSON 並將其轉換為類型 T。 使用傳遞給方法的 Utf8JsonReader 讀取 JSON。 無需擔心處理部分數據,因為序列化程序會傳遞當前 JSON 范圍的所有數據。 因此,不需要調用 SkipTrySkip,也不需要驗證 Read 是否返回 true
  • 重寫 Write 方法以序列化 T 類型的傳入對象。 使用傳遞給方法的 Utf8JsonWriter 寫入 JSON。
  • 僅當需要時才重寫 CanConvert 方法。 當要轉換的類型屬於類型 T 時,默認實現會返回 true。 因此,僅支持類型 T 的轉換器不需要重寫此方法。 有關的確需要重寫此方法的轉換器的示例,請參閱本文后面的多態反序列化部分。

 可以參閱內置轉換器源代碼作為用於編寫自定義轉換器的參考實現。

屬性上的 [JsonConverter]

  1. 將轉換器類的實例添加到 JsonSerializerOptions.Converters 集合中。
  2. 將 [JsonConverter] 特性應用於需要自定義轉換器的屬性
JsonSerializerOptions op = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters = { new MYEnumToUpperStingConverter() },//將轉換器類的實例添加到 JsonSerializerOptions.Converters 集合中。

    WriteIndented = true,
};

WeatherForecastWithEnum wf=new WeatherForecastWithEnum();   
string wfw= JsonSerializer.Serialize(wf, op);
WeatherForecastWithEnum wff=JsonSerializer.Deserialize<WeatherForecastWithEnum>(wfw,op);
Console.WriteLine( wfw);
public class MYEnumToUpperStingConverter : JsonConverter<Summary>
{

    public override Summary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return (Summary)Enum.Parse(typeToConvert, reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, Summary value, JsonSerializerOptions options)
    {
        writer.WriteStringValue( Enum.GetName(value));
    }
}


public class WeatherForecastWithEnum
{
   
    public DateTimeOffset Date { get; set; } = DateTime.Now;
    public int TemperatureCelsius { get; set; } = new Random().Next(1000);

    [JsonConverter(typeof(MYEnumToUpperStingConverter))]//將 [JsonConverter] 特性應用於需要自定義轉換器的屬性。
    public Summary Summaryp { get; set; } = Summary.Cold;

    [JsonConverter(typeof(MYEnumToUpperStingConverter))]
    public Summary Summaryp2 { get; set; } = Summary.Cold;
}

public enum Summary
{
    Cold, Cool, Warm, Hot
}

 類型上的 [JsonConverter]

  1. 將轉換器類的實例添加到 JsonSerializerOptions.Converters 集合中。
  2.  將 [JsonConverter] 屬性應用於表示自定義值類型的類或結構。

 

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

namespace SystemTextJsonSamples;

public class test
{

    static void Main()
    {
        Weather weather = new Weather();
          JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true,
         
        };

    string tem=    JsonSerializer.Serialize(weather, options);
        Console.WriteLine(tem);
        Weather weather2 = JsonSerializer.Deserialize<Weather>(tem);
        Console.Read();
    }

}
/* 輸出
{
  "Temperatur": "23C"
}*/
//解析 之所能輸出這個結果 是因為序列化和反序列化時,類型的[JsonConverter(typeof(TemperatureConverter))] 特性在起作用
如果類型不加特性[JsonConverter(typeof(TemperatureConverter))] 將輸出以下結果:
{
  "Temperatur": {
    "Degrees": 23,
    "IsCelsius": true,
    "IsFahrenheit": false
  }
}



public class Weather { public Temperature Temperatur { get; set; } = new Temperature(23, true); } [JsonConverter(typeof(TemperatureConverter))] public struct Temperature { public Temperature(int degrees, bool celsius) { Degrees = degrees; IsCelsius = celsius; } public int Degrees { get; } public bool IsCelsius { get; } public bool IsFahrenheit => !IsCelsius; public override string ToString() => $"{Degrees}{(IsCelsius ? "C" : "F")}"; public static Temperature Parse(string input) { int degrees = int.Parse(input.Substring(0, input.Length - 1)); bool celsius = input.Substring(input.Length - 1) == "C"; return new Temperature(degrees, celsius); } } public class TemperatureConverter : JsonConverter<Temperature> { public override Temperature Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => Temperature.Parse(reader.GetString()!); public override void Write(Utf8JsonWriter writer, Temperature temperature, JsonSerializerOptions options) => writer.WriteStringValue(temperature.ToString()); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM