Newtonsoft.Json在.NET5/Core和.NETFramework上的不同行为

c#

以下程序在 .NET 5(或 .NET Core)和 .NET Framework 上运行时会产生不同的结果。

为什么行为不同?我不是在寻找反序列化问题的解决方案;我的目标是了解会发生什么。

class Versioned 
{
    public Version V {get; set;} = new Version(1,0);
}

static void Main(string[] args)
{
    // Serialised with version Newtonsoft.Json 9.0.1
    var json = "{"V":{"Major":2,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}}";

    Console.WriteLine($".NET: {System.Environment.Version}");
    Console.WriteLine($"Json.NET: {System.Reflection.Assembly.GetAssembly(typeof(Newtonsoft.Json.JsonConvert))}");

    Console.WriteLine(json);
    
    try 
    {
        var b = Newtonsoft.Json.JsonConvert.DeserializeObject<Versioned>(json);
        Console.WriteLine(b.V);
    } 
    catch (Exception ex) { Console.WriteLine(ex.GetBaseException().Message); }
}

在 .NET 5 上:输出是(为了可读性而格式化):

.NET: 5.0.1
Json.NET: Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
{
    "V": {
        "Major": 2,
        "Minor": 0,
        "Build": -1,
        "Revision": -1,
        "MajorRevision": -1,
        "MinorRevision": -1
    }
}

出现此错误:

无法将当前 JSON 对象(例如 {"name":"value"})反序列化为类型“System.Version”,因为该类型需要 JSON 字符串值才能正确反序列化。

要修复此错误,请将 JSON 更改为 JSON 字符串值或更改反序列化类型,使其成为可以反序列化的普通 .NET 类型(例如,不是像整数这样的原始类型,不是像数组或列表这样的集合类型)来自 JSON 对象。还可以将 JsonObjectAttribute 添加到类型以强制它从 JSON 对象反序列化。路径“V.Major”,第 1 行,位置 14。

在 .NET Framework 4.6.2 上,输出是:

.NET: 4.0.30319.42000
Json.NET: Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
{
    "V": {
        "Major": 2,
        "Minor": 0,
        "Build": -1,
        "Revision": -1,
        "MajorRevision": -1,
        "MinorRevision": -1
    }
}
1.0

此外,由于没有默认值,.NET 4.6.2 上的行为再次不同。

class Versioned
{
    public Version V { get; set; }// = new Version(1, 0);
}

在 .NET 5.0 上,输出是相同的:

(...)
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Version' because...

在 .NET Framework 4.6.2 上,输出现在是:

(...)
Version's parameters must be greater than or equal to zero.
Parameter name: build

据我所知,System.Version这些 .NET 版本之间的类并没有改变(在外部),这种改变应该在这里起作用(我只知道ISpanFormattable区别)。我查看了源代码(.NET Core 版本和.NET Framework 4.8 版本),但我看不到任何可以解释不同行为的内容。

回答

看起来 Json.NETVersionConverter在 .NET Core 2.2 中有一个新的东西,它知道如何正确地序列化和反序列化Version实例。当您使用 .NET Core 2.2+ 时,它会自动获取并使用。

使用VersionConverter,Json.NET 希望将您的Version对象序列化为字符串"1.0",而不是 JSON 对象。如果您json通过序列化Versioned.NET Core 2.2+ 上的新实例在帖子中创建字符串:

var json = Newtonsoft.Json.JsonConvert.SerializeObject(new Versioned());

你会看到它返回 eg {"V":"1.0"}

同样,VersionConverter只知道如何读版本字符串,例如"1.0",不知道如何处理的对象包含做MajorMinor等等。

有关更多信息,请参阅此问题。
请参阅此处运行的代码。


以上是Newtonsoft.Json在.NET5/Core和.NETFramework上的不同行为的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>