[.Net Core 3.0+/.Net 5] System.Text.Json中時間格式化

簡介

.Net Core 3.0開始全新推出了一個名為System.Text.Json的Json解析庫,用於序列化和反序列化Json,此庫的設計是為了取代Json.Net(Newtonsoft.Json)

時間格式化的不足

System.Text.Json的優點就不說了,來說一下不完善的地方,畢竟一個新事物出來,不可能十全十美的,用的最多的就是時間的格式化

官方文檔:在 System.Text.Json 中,具有內置支持的唯一格式是 ISO 8601-1:2019,因為它被廣泛採用、意義明確並且可精確地進行往返。 若要使用任何其他格式,請創建自定義轉換器

ISO 8601-1:2019通俗的說就是時間格式化為2020-11-11T21:08:18ISO 8601-1:2019標準參考:ISO官網 | 百度百科 | wikipedia

但我們一般用的時候不想要這種格式,因為中間有一個T,前端處理起來很麻煩,最好還是返回指定的時間格式,例如:yyyy-MM-ddyyyy-MM-dd HH:mm:ss

解決方案

既然官方不內置提供指定時間格式化的方式,那就沒辦法了嗎,查閱文檔發現,雖然無法簡單的實現功能,但是可以通過創建自定義轉換器來實現相應功能

文檔地址:微軟官方文檔

以下是一個自定義時間轉化器的完整實現:

public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}

使用

代碼看起來非常簡單是不是,只需要重寫ReadWrite,但是我們只是寫了一個自定義轉換器,怎麼讓它生效呢,請往下看:

JsonSerializer.Serialize()JsonSerializer.Deserialize()方法都接受一個JsonSerializerOptions類型的配置項參數

JsonSerializerOptions添加Converters就可以了

JsonSerializerOptions options = new JsonSerializerOptions()
{
    Converters.Add(new DateTimeConverterUsingDateTimeParse())
}

string jsonString = JsonSerializer.Serialize(data, options);

至此,我們已經實現使用System.Text.Json庫指定時間格式字符串進行序列化和反序列化,你甚至可以把yyyy-MM-dd HH:mm:ss做成參數來更自由的指定格式化字符串

基準測試

但是凡事有利就有弊,官方文檔也說得很清楚了:

使用自定義轉換器與使用序列化程序的本機實現相比,此方法的性能大大降低

有人就想知道了,到底會影響多少性能呢,我進行了一項基準測試,序列化100000條數據,包含時間處理,模型如下:

public class Dto
{
    public string Name { get; set; }

    public string Phone { get; set; }

    public DateTime DateTime { get; set; }
}


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i7-6700K CPU 4.00GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=5.0.100-rc.2.20479.15
  [Host]     : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT  [AttachedDebugger]
  DefaultJob : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT

  System.Text.Json Version 5.0.0
  Newtonsoft.Json Version 12.0.3
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
SystemTextJsonConverterDate 67.36 ms 0.489 ms 0.458 ms 2250.0000 750.0000 750.0000 52.15 MB
SystemTextJson 53.26 ms 0.231 ms 0.180 ms 500.0000 500.0000 500.0000 48.67 MB
NewtonsoftJsonConverterDate 123.42 ms 1.847 ms 1.727 ms 5800.0000 2200.0000 600.0000 51.61 MB
NewtonsoftJson 109.41 ms 0.977 ms 0.913 ms 4800.0000 2000.0000 600.0000 50.82 MB

結語

可以看到性能確實會有影響,但是可以忽略不計了,100000條才差10ms。

同時可以發現System.Text.Json性能是Newtonsoft.Json的兩倍

推薦大家以後在滿足需求的情況下盡量使用內置的System.Text.Json