.NET Core 3.0中使用Json.NET(Newtonsoft.Json)反序化(Deserialize)包含TimeSpan类型字符串报错( Newtonsoft.Json.JsonSerializationException : Cannot deserialize the current JSON object (e.g. {“name”:“value”}) into type 'System.TimeSpan' ),本文主要介绍一下出错原因及解决方法。

1、JSON字符串及异常信息

JSON字符串

{
"userId": null,
"accessToken": null,
"refreshToken": null,
"sessionId": null,
"cookieExpireTimeSpan": {
"ticks": 0,
"days": 0,
"hours": 0,
"milliseconds": 0,
"minutes": 0,
"seconds": 0,
"totalDays": 0,
"totalHours": 0,
"totalMilliseconds": 0,
"totalMinutes": 0,
"totalSeconds": 0
},
"claims": null,
"success": false,
"errors": [
{
"code": "Forbidden",
"description": "Invalid username unknown!"
}
]
}

异常信息

  Newtonsoft.Json.JsonSerializationException : Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.TimeSpan' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly.
To fix this error either change the JSON to a JSON primitive value (e.g. string, number, boolean, null) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'cookieExpireTimeSpan.ticks', line 1, position 103.

2、报错原因及解决方法

异常原因

.NET Core 3.0 用新的内置JSON序列化程序System.Text.Json  替换了 JSON.NET。该序列化器不支持TimeSpan。新的序列化器更快,在大多数情况下不会分配,但并不能涵盖JSON.NET所做的所有情况。

无论如何,都没有标准的方式来表示JSON中的日期或时间段。甚至ISO8601格式也是一种约定,不是标准本身的一部分。JSON.NET使用可读的格式(23:00:00),但是ISO8601的持续时间格式看起来像P23DT23H(23天23小时)或P4Y(4年)。

解决方法

使用JSON.NET。这些步骤在文档中进行了描述:

1) 添加对Microsoft.AspNetCore.Mvc.NewtonsoftJson的包引用。

2) 配置Startup.ConfigureServices以调用AddNewtonsoftJson

在Startup.ConfigureServices中配置:

services.AddMvc()
.AddNewtonsoftJson();

或者

对该类型使用自定义转换器

例如:

public class TimeSpanToStringConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var value=reader.GetString();
return TimeSpan.Parse(value);
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}

并且在Startup.ConfigureServicesAddJsonOptions,如:

services.AddControllers()                    
.AddJsonOptions(options=>
options.JsonSerializerOptions.Converters.Add(new TimeSpanToStringConverter()));