.Net Core 3.0 TimeSpan反序列化错误 [英] .Net Core 3.0 TimeSpan deserialization error
问题描述
我正在使用.Net Core 3.0,并且需要使用Newtonsoft.Json反序列化以下字符串:
I am using .Net Core 3.0 and have the following string which I need to deserialize with Newtonsoft.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.
读取HttpResponseMessage的内容时,实际上会发生错误字符串:
The error string actually happens when reading the content of HttpResponseMessage:
var httpResponse = await _client.PostAsync("/api/auth/login", new StringContent(JsonConvert.SerializeObject(new API.Models.Request.LoginRequest()), Encoding.UTF8, "application/json"));
var stringResponse = await httpResponse.Content.ReadAsStringAsync();
服务器控制器方法返回:
The server controller method returns:
return new JsonResult(result) { StatusCode = whatever; };
推荐答案
REST API服务不应生成这样的JSON字符串.我敢打赌,以前的版本会返回00:0:00
而不是TimeSpan对象的所有属性.
The REST API service shouldn't produce such a JSON string. I'd bet that previous versions returned 00:0:00
instead of all the properties of a TimeSpan object.
这样做的原因是.NET Core 3.0 System.Text.Json .此序列化器不支持TimeSpan .新的序列化器更快,在大多数情况下不会分配,但不会涵盖JSON.NET所做的所有 .
The reason for this is that .NET Core 3.0 replaced JSON.NET with a new, bult-in JSON serializer, System.Text.Json. This serializer doesn't support TimeSpan. The new serializer is faster, doesn't allocate in most cases, but doesn't cover all the cases JSON.NET did.
在任何情况下,都没有 no 标准方法来表示JSON中的日期或时间段.甚至ISO8601格式也是一种约定,而不是标准本身的一部分. JSON.NET使用可读格式(23:00:00
),但是 ISO8601的持续时间格式看起来例如P23DT23H
(23天23小时)或P4Y
(4年).
In any case, there's no standard way to represent dates or periods in JSON. Even the ISO8601 format is a convention, not part of the standard itself. JSON.NET uses a readable format (23:00:00
), but ISO8601's duration format would look like P23DT23H
(23 days, 23 hours) or P4Y
(4 years).
一种解决方案是回到JSON.NET.步骤在文档中进行了描述:
One solution is to go back to JSON.NET. The steps are described in the docs:
更新Startup.ConfigureServices以调用AddNewtonsoftJson.
Update Startup.ConfigureServices to call AddNewtonsoftJson.
services.AddMvc()
.AddNewtonsoftJson();
另一种选择是对该类型使用自定义转换器,例如:
Another option is to use a custom converter for that type, eg :
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());
}
}
并使用AddJsonOptions
将其注册在Startup.ConfigureServices
中,例如:
And register it in Startup.ConfigureServices
with AddJsonOptions
, eg :
services.AddControllers()
.AddJsonOptions(options=>
options.JsonSerializerOptions.Converters.Add(new TimeSpanToStringConverter()));
这篇关于.Net Core 3.0 TimeSpan反序列化错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!