使用 System.Text.Json.JsonSerializer 反序列化到 ProblemDetails 时出错。 .Net 核心 3.0
Error when deserializing to ProblemDetails with System.Text.Json.JsonSerializer. .Net Core 3.0
考虑以下 json:
{
"title": "SOME TITEL",
"status": 500,
"detail": "Some detail",
"errors": [
{
"Parameter": "SOME VALUE",
"Code": "SOME CODE",
"Message": "SOME MESSAGE",
"Details": "SOME EXTRA DETAILS"
}
]
}
它由 API 响应生成,该响应构建了如下问题详细信息:
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError;
Detail = "DETAIL";
Title = "TITLE";
};
var customClass = new CustomCalss
{
Code = "INTERNAL_SERVER_ERROR",
Message = "Some message",
Details = "Extra details"
};
problemDetails.Extensions.Add(new KeyValuePair<string, object>("errors", new [] { customClass }));
当尝试使用 System.Text.JsonSerialiser 将 json 反序列化为问题详细信息时,我发现了以下问题:
- 状态、代码和标题未反序列化为问题详细信息属性,它们为空
- 扩展数据未反序列化。
我正在像这样测试这种行为:
var json = @"{
""title"": ""SOME TITLE"",
""status"": 500,
""detail"": ""Some detail"",
""errors"": [
{
""Parameter"": null,
""Code"": ""SOME CODE"",
""Message"": ""SOME MESSAGE"",
""Details"": ""SOME EXTRA DETAILS""
}
]
}";
var result = JsonSerializer.Deserialize<ProblemDetails>(json);
Assert.NotNull(result.Detail);
Assert.NotNull(result.Title);
var customClass = Assert.IsType<CustomCalss[]>(result.Extensions["errors"]);
var error = customClass.First();
Assert.Equal("INTERNAL_SERVER_ERROR", error.Code);
有什么见解吗?
C# 是区分大小写的语言,您的 JSON 字符串有问题,密钥必须与目标 class 的 属性 完全相同。我把 "title" 改成了 "Title" 然后得到了正确的值,附在这里供大家参考:
11 月 20 日更新:
没注意到这是一个MVC内部class,我们现在可以在本地框简单地重现这个问题,但是在网上查看了源代码和已知问题,没有存在相关问题。所以我针对这个问题报告了一个新的bug,附在这里供大家参考
https://github.com/aspnet/AspNetCore/issues/17250
11 月 22 日更新:
这已被确认为 ASP.NET Core 3.0 的一个错误,并在 3.1 版本中修复,请升级到 3.1-preview2。或者,您可以根据我们在 3.1 中的实现指定自定义 JsonConverter 作为反序列化时传递的 JsonSerializerOptions 的一部分 - https://github.com/aspnet/AspNetCore/blob/release/3.1/src/Mvc/Mvc.Core/src/Infrastructure/ValidationProblemDetailsJsonConverter.cs
考虑以下 json:
{
"title": "SOME TITEL",
"status": 500,
"detail": "Some detail",
"errors": [
{
"Parameter": "SOME VALUE",
"Code": "SOME CODE",
"Message": "SOME MESSAGE",
"Details": "SOME EXTRA DETAILS"
}
]
}
它由 API 响应生成,该响应构建了如下问题详细信息:
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError;
Detail = "DETAIL";
Title = "TITLE";
};
var customClass = new CustomCalss
{
Code = "INTERNAL_SERVER_ERROR",
Message = "Some message",
Details = "Extra details"
};
problemDetails.Extensions.Add(new KeyValuePair<string, object>("errors", new [] { customClass }));
当尝试使用 System.Text.JsonSerialiser 将 json 反序列化为问题详细信息时,我发现了以下问题:
- 状态、代码和标题未反序列化为问题详细信息属性,它们为空
- 扩展数据未反序列化。
我正在像这样测试这种行为:
var json = @"{
""title"": ""SOME TITLE"",
""status"": 500,
""detail"": ""Some detail"",
""errors"": [
{
""Parameter"": null,
""Code"": ""SOME CODE"",
""Message"": ""SOME MESSAGE"",
""Details"": ""SOME EXTRA DETAILS""
}
]
}";
var result = JsonSerializer.Deserialize<ProblemDetails>(json);
Assert.NotNull(result.Detail);
Assert.NotNull(result.Title);
var customClass = Assert.IsType<CustomCalss[]>(result.Extensions["errors"]);
var error = customClass.First();
Assert.Equal("INTERNAL_SERVER_ERROR", error.Code);
有什么见解吗?
C# 是区分大小写的语言,您的 JSON 字符串有问题,密钥必须与目标 class 的 属性 完全相同。我把 "title" 改成了 "Title" 然后得到了正确的值,附在这里供大家参考:
11 月 20 日更新:
没注意到这是一个MVC内部class,我们现在可以在本地框简单地重现这个问题,但是在网上查看了源代码和已知问题,没有存在相关问题。所以我针对这个问题报告了一个新的bug,附在这里供大家参考
https://github.com/aspnet/AspNetCore/issues/17250
11 月 22 日更新: 这已被确认为 ASP.NET Core 3.0 的一个错误,并在 3.1 版本中修复,请升级到 3.1-preview2。或者,您可以根据我们在 3.1 中的实现指定自定义 JsonConverter 作为反序列化时传递的 JsonSerializerOptions 的一部分 - https://github.com/aspnet/AspNetCore/blob/release/3.1/src/Mvc/Mvc.Core/src/Infrastructure/ValidationProblemDetailsJsonConverter.cs