如何让 System.Text.Json 将对象反序列化为它们的原始类型?

How do I get System.Text.Json to deserialize objects into their original type?

我正在使用 .NET 5.0 中的 POCO class,我需要在浏览器之间进行序列化和反序列化,这是在我不想告诉的库中用户必须使用哪些序列化器。

所以我试图让它与 Newtonsoft.Json 和 System.Text.Json 一起工作。

我的问题是在 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 抛出异常:

Expected value to be System.String but was 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 的讨论:

This is by design (and unlikely to change). Since the object type could map the JSON payload to any .NET type, while deserializing, the JsonSerializer returns a boxed JsonElement instead that points to the JSON token itself. We don't try to infer or guess the .NET type from the JSON payload during deserialization and hence, the caller (who has enough context) would need to turn the returned JsonElement into the expected .NET type.

如果您正在尝试我正在尝试做的事情,请在实用程序库中创建一个 POCO class,它可以由库的客户端序列化和反序列化,而不需要对用户进行任何特殊的努力图书馆,不要使用对象。

在我的例子中,我有一个字段可能包含字符串、整数、双精度数、小数点或日期时间。我将不得不用每个单独的可空字段替换它。