1. 程式人生 > >[.Net Core 3.0+/.Net 5] System.Text.Json中時間格式化

[.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:18`**。**`ISO 8601-1:2019`**標準參考:[ISO官網](https://www.iso.org/standard/70907.html) | [百度百科](https://baike.baidu.com/item/ISO%208601/3910715) | [wikipedia](https://en.wikipedia.org/wiki/ISO_8601) 但我們一般用的時候不想要這種格式,因為中間有一個`T`,前端處理起來很麻煩,最好還是返回指定的時間格式,例如:`yyyy-MM-dd`、`yyyy-MM-dd HH:mm:ss`。 ### 解決方案 既然官方不內建提供指定時間格式化的方式,那就沒辦法了嗎,查閱文件發現,雖然無法簡單的實現功能,但是可以通過建立自定義轉換器來實現相應功能 文件地址:[微軟官方文件](https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#specify-date-format) **以下是一個自定義時間轉化器的完整實現:** ``` public class DateTimeConverterUsingDateTimeParse : JsonConverter { 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")); } } ``` ### 使用 程式碼看起來非常簡單是不是,只需要重寫`Read`和`Write`,但是我們只是寫了一個自定義轉換器,怎麼讓它生效呢,請往下看: `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; } } ``` ``` ini 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`