c# - Newtonsoft.Json 在 .NET 5 / Core 和 .NET Framework 上的不同行为
问题描述
以下程序在 .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 对象。如果您通过序列化.NET Core 2.2+ 上json
的新实例在帖子中创建字符串:Versioned
var json = Newtonsoft.Json.JsonConvert.SerializeObject(new Versioned());
您会看到它返回例如{"V":"1.0"}
.
同样,VersionConverter
只知道如何读取版本字符串,例如"1.0"
, 并且不知道如何处理包含 , 等的Major
对象Minor
。
推荐阅读
- java - XSL - 排除对 ACCESS_EXTERNAL_STYLESHEET 的访问
- kubernetes - 如何将普罗米修斯适配器移动到另一个命名空间?
- verilog - “并发分配或输出端口连接的目标应该是网络类型”
- c# - 三元运算符的用法没有错误的情况
- flutter - 用倒色进行颤振绘制
- scala - 在 Scala 中序列化函数时避免捕获 `this`
- c++ - [[maybe_unused]] 与结构化绑定?
- c# - gRPC C#服务器端,等到客户端关闭连接?
- xamarin.forms - Xamarin Forms 4.4 + 中是否仍需要此 ExportRenderer
- html - 如何在 .ts 文件中以角度创建按钮并添加点击事件