System.Text.Json 目前無法反/序列化轉換 TimeSpan 型別,但從 .NET 5 的 Milestone可以知道,這功能將會包含在 .NET 5 之中,在此之前,如果真的要對 TimeSpan 做反/序列化轉換,可以自行實作 JsonConverter 來處理。
根據官方時程表,.NET 5 將會在 2020 年 11 月發布,所以這篇作法很可能到那時候,就再也不需要了。
實作 JsonTimeSpanConverter
直接在 System.Text.Json.Serialization 命名空間底下,實作 JsonConverter<TimeSpan> 來建立一個可以用來轉換 TimeSpan 的 JsonConverter,程式碼參考如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| using System.Globalization;
namespace System.Text.Json.Serialization { public class JsonTimeSpanConverter : JsonConverter<TimeSpan> { public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) throw new NotSupportedException(); if (typeToConvert != typeof(TimeSpan)) throw new NotSupportedException();
return TimeSpan.ParseExact(reader.GetString(), "c", CultureInfo.InvariantCulture); }
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("c", CultureInfo.InvariantCulture)); } } }
|
使用方式
假設我們有下面 DemoClass 這個類別,只要在型別為 TimeSpan 的屬性上面,加上 [JsonConverter(typeof(JsonTimeSpanConverter))],這樣 JsonSerializer 在做反/序列化轉換時,就會使用我們自行實作的 JsonTimeSpanConverter 來做轉換。
1 2 3 4 5
| public class DemoClass { [JsonConverter(typeof(JsonTimeSpanConverter))] public TimeSpan TimeSpan { get; set; } }
|
這樣下面的程式就可以正常反/序列化轉換了,而不會出現 System.Text.Json.JsonException: The JSON value could not be converted to System.TimeSpan. 這樣的錯誤了。
1 2 3 4 5 6 7 8 9 10
| var obj = new DemoClass { TimeSpan = new TimeSpan(1, 0, 0) }; Console.WriteLine(JsonSerializer.Serialize(obj));
var jsonString = "{\"TimeSpan\": \"01:00:00\"}"; Console.WriteLine(JsonSerializer.Deserialize<DemoClass>(jsonString).TimeSpan);
|
如果是用 Json.NET
如果是使用 Json.NET 了話,就不需要自己寫 JsonConverter,他內建的 SerializeObject 和 DeserializeObject 就可以直接反序列化/序列化 TimeSpan 型別,只能說 Json.NET 功能還是比較完整呀。
以上面的測試範例改用 Newtonsoft.Json,直接寫這樣就搞定:
1 2 3 4 5 6 7 8 9 10
| var obj = new DemoClass { TimeSpan = new TimeSpan(1, 0, 0) }; Console.WriteLine(JsonConvert.SerializeObject(obj));
var jsonString = "{\"TimeSpan\": \"01:00:00\"}"; Console.WriteLine(JsonConvert.DeserializeObject<DemoClass>(jsonString).TimeSpan);
|
參考資料: