c# - 如何让 System.Text.Json 将对象反序列化为其原始类型?
问题描述
我正在使用 .NET 5.0 中的 POCO 类,我需要对浏览器进行序列化和反序列化,这是在一个库中,我不想告诉用户他们必须使用哪些序列化程序。
所以我试图让它与 Newtonsoft.Json 和 System.Text.Json 一起工作。
我的问题是存储在类型为 object 的字段中的值没有被反序列化为 System.Text.Json 中的原始类型。
using Shouldly;
using Xunit;
using SJ = System.Text.Json;
using NJ = Newtonsoft.Json;
public class SerializationTests
{
[Fact]
public void TestNJ()
{
var nvp = new NVP { Name = "a name", Value = "a value" };
var s = NJ.JsonConvert.SerializeObject(nvp);
var d = NJ.JsonConvert.DeserializeObject<NVP>(s);
d.ShouldBeEquivalentTo(nvp);
}
[Fact]
public void TestSJ()
{
var nvp = new NVP { Name = "a name", Value = "a value" };
var s = SJ.JsonSerializer.Serialize(nvp);
var d = SJ.JsonSerializer.Deserialize<NVP>(s);
d.ShouldBeEquivalentTo(nvp);
}
}
TestNJ 通过。
TestSJ 抛出异常:
预期值为 System.String 但为 System.Text.Json.JsonElement'
在调试器中很清楚发生了什么。
在 TestNJ() 和 TestSJ() 中,一开始nvp
都有以下值:
nvp: {NVP}
Name [string]: "a name"
Value [object]: " a value"
在序列化之后,两者都s
具有我期望的值:
"{\"Name\":\"a name\",\"Value\":\"a value\"}"
但是在 TestNJ() 中,在反序列化之后,d
具有以下值:
d: {NVP}
Name [string]: "a name"
Value [object]: " a value"
在 TestSJ() 中,d
具有以下值:
d: {NVP}
Name [string]: "a name"
Value [object]: ValueKind = String: "a value"
这里发生了什么?如何让 System.Text.Json 实际反序列化这种类型?
解决方案
丹尼斯指向https://github.com/dotnet/runtime/issues/31408并作为https://github.com/dotnet/runtime/issues/29960 的副本关闭。
所以答案是,你没有。
来自 GitHub 上的讨论:
这是设计使然(并且不太可能改变)。由于对象类型可以将 JSON 有效负载映射到任何 .NET 类型,因此在反序列化时,JsonSerializer 返回一个装箱的 JsonElement,而不是指向 JSON 令牌本身。在反序列化期间,我们不会尝试从 JSON 有效负载推断或猜测 .NET 类型,因此,调用者(具有足够上下文)需要将返回的 JsonElement 转换为预期的 .NET 类型。
如果您正在尝试我正在尝试做的事情,请在实用程序库中创建一个 POCO 类,该类可以由库的客户端进行序列化和反序列化,而不需要对库的用户进行任何特别的努力,不要使用 object.
就我而言,我有一个可能包含字符串、int、double、decimal 或 datetime 的字段。我将不得不用一个单独的可为空字段替换它。
推荐阅读
- mosaic-decisions - Mosaic-Decisions:表达式中支持的不同时区
- sql - 如何对 SQL 中的列值使用“不喜欢”
- spring - 使用 Spring - Thymeleaf 加载了一些图像
- r - 如何解决无效符号坐标错误
- image - MASK R-CNN,为什么val_mrcnn_bbox_loss和val_mrcnn_mask_loss都是0?
- javascript - JS中的变量提升
- spock - 放心 - 在多次重定向后验证最后一页的 url
- cmake - 找不到“Eigen3”(请求的版本 3)提供的包配置文件?
- python - 在数据框中创建一个新列,其中包含列表中该行的其他列的值
- html - 实时服务器不刷新vscode中的页面