TimeSpan的系统文本JsonSerializer反序列化

Posted

技术标签:

【中文标题】TimeSpan的系统文本JsonSerializer反序列化【英文标题】:System Text JsonSerializer Deserialization of TimeSpan 【发布时间】:2020-04-20 18:03:32 【问题描述】:

在研究如何使用 Newtonsoft 的 JSON.net 反序列化 TimeSpan 时,我在当前项目中遇到了不使用 Json.net 的代码。它使用System.Text.Json.JsonSerializer 并且似乎在反序列化TimeSpan 属性的操作中不会失败,根据我正在运行的单元测试

我想,.Net Core 3.1 已经超越了反序列化 TimeSpan历史问题,一切都很好。因此在最新版本的 Linqpad 6(使用 .NET Core)中启动了一个测试用例来验证,令我懊恼的是它失败了。


所以问题是,TimeSpan 是否可以使用任一库进行序列化/反序列化(如果可以,如何)......或者我下面的测试用例在某些方面存在缺陷?


代码

public class Project  public TimeSpan AverageScanTime  get; set;  

Linqpad C# 代码

var newP = new Project()  AverageScanTime = TimeSpan.FromHours(1) ;

newP.Dump("New one");

var json = System.Text.Json.JsonSerializer.Serialize(newP);

json.Dump("JSON serialized");

System.Text.Json.JsonSerializer.Deserialize<Project>(json)
                               .Dump("JSON Deserialize");

反序列化失败

【问题讨论】:

看起来像 .Net Core 3.0 TimeSpan deserialization erro 的副本,同意吗? @dbc 否,因为该答案表明 .NET 核心的 json 处理是 in-part 创建来处理时间跨度的,但并非所有时间跨度都是相同的。我说的是 .Net 的时间跨度作为输入,但它失败了...... 该答案表明 .NET 核心的 json 处理部分是为了处理时间跨度而创建的 - 我没有看到。答案指出,REST API 服务不应该生成这样的 JSON 字符串。 这里发生的情况是,新的序列化程序只是将 TimeSpan 的所有属性序列化为 JSON 对象,因为它没有该结构的特殊情况,然后由于所有这些属性都是不可变的,因此无法反序列化。像链接答案中的JsonConverter&lt;TimeSpan&gt; 应该可以解决问题。 【参考方案1】:

TimeSpan 的 JsonSerializer 似乎将添加到 Future(从 .NET 6 里程碑中删除)。您可以在Future milestone 或此issue 中跟踪此问题。

这时候可以自己实现JsonTimeSpanConverter。或者您可以安装Macross.Json.Extensions nuget 包并按照instruction 进行反序列化。

【讨论】:

遗憾的是,它尚未添加到 .NET Core 5。Source 今天它已移至"Future",因此也不在.Net 6中。【参考方案2】:

Poy Chang 回答的补充

Swagger (Swashbuckle) 也需要配置

services.AddSwaggerGen(options =>

    options.MapType(typeof(TimeSpan), () => new OpenApiSchema
    
        Type = "string",
        Example = new OpenApiString("00:00:00")
    );
);

【讨论】:

以上是关于TimeSpan的系统文本JsonSerializer反序列化的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ISO8601 TimeSpan 转换为 C# TimeSpan?

如何将 TimeSpan 序列化为 XML

WPF中TimeSpan的坑

查找 TimeSpan 集合的平均值

将字符串解析为 TimeSpan

在 C# 中处理 TimeSpan 异常