首页 > 解决方案 > 如何让 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 实际反序列化这种类型?

标签: c#jsonasp.net-core.net-coresystem.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 的字段。我将不得不用一个单独的可为空字段替换它。


推荐阅读