.Net Core 3.0 TimeSpan 反序列化错误 - 在 .Net 5.0 中修复 [英] .Net Core 3.0 TimeSpan deserialization error - Fixed in .Net 5.0

查看:22
本文介绍了.Net Core 3.0 TimeSpan 反序列化错误 - 在 .Net 5.0 中修复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 .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 用新的内置 JSON 序列化程序替换 JSON.NETSystem.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.

在任何情况下,都没有标准方法来表示 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());
    }
}

并在 Startup.ConfigureServices 中使用 AddJsonOptions 注册它,例如:

And register it in Startup.ConfigureServices with AddJsonOptions, eg :

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

这篇关于.Net Core 3.0 TimeSpan 反序列化错误 - 在 .Net 5.0 中修复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆