.NET 8与.NET 4.8跨版本JSON序列化Newtonsoft.Json异常
跨.NET版本(.NET 8与.NET 4.8)JSON序列化/反序列化类型绑定问题
在.NET 8和.NET 4.8进程间传递object类型数据时,需通过TypeNameHandling携带类型信息实现序列化/反序列化,但使用Newtonsoft.Json v13.0.3时,.NET 4.8反序列化阶段会因无法识别.NET 8中的System.Private.CoreLib程序集抛出异常,当前采用逐行修改JSON的低效方法,需在反序列化阶段通过SerializationBinder实现更优雅的解决方案。
异常信息
Newtonsoft.Json.JsonSerializationException
HResult=0x80131500
Message=Error resolving type specified in JSON 'System.Double[], System.Private.CoreLib'.JsonSerializationException: Could not load assembly 'System.Private.CoreLib'.
测试代码
TestData(.NET Standard 2.0)
using System; namespace Data { using System.Collections.Generic; public class TestData { public object[] data; } }
WriteJson(.NET 8)
namespace WriteJson { using Data; using Newtonsoft.Json; internal class Program { static void Main(string[] args) { var testData = new TestData() { data = new object[] { new[] { 1.0, 2.0, 3.0 }, new[] { 4.0, 5.0, 6.0 }, } }; var serSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }; var serializer = JsonSerializer.Create(serSettings); var fileName = @"C:\TEMP\TestData.json"; using (var fs = new StreamWriter(fileName, false)) using (var writer = new JsonTextWriter(fs)) { serializer.Serialize(writer, testData); writer.Close(); fs.Close();; } } } }
ReadJson(.NET 4.8)
namespace ReadJson { using Newtonsoft.Json; using System.IO; using Data; internal class Program { static void Main(string[] args) { var serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }; var fileName = @"C:\TEMP\TestData.json"; using (var reader = new StreamReader(fileName)) { var serializer = JsonSerializer.Create(serializerSettings); var result = (TestData)serializer.Deserialize(reader, typeof(TestData)); } } } }
生成的JSON内容
{ "data": [ { "$type": "System.Double[], System.Private.CoreLib", "$values": [ 1.0, 2.0, 3.0 ] }, { "$type": "System.Double[], System.Private.CoreLib", "$values": [ 4.0, 5.0, 6.0 ] } ] }
解决方案:自定义SerializationBinder处理跨版本程序集映射
在.NET 4.8的反序列化逻辑中,实现自定义SerializationBinder,将.NET Core/.NET 5+系列的System.Private.CoreLib程序集映射到.NET Framework对应的基础程序集。
自定义Binder代码
public class CrossNetVersionBinder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { // 拦截System.Private.CoreLib程序集的类型解析请求 if (assemblyName.Equals("System.Private.CoreLib", StringComparison.OrdinalIgnoreCase)) { // 针对基础类型数组直接返回对应类型 switch (typeName) { case "System.Double[]": return typeof(double[]); case "System.Int32[]": return typeof(int[]); case "System.String[]": return typeof(string[]); // 可根据实际传递的类型扩展更多case default: // 通用处理:替换程序集名为mscorlib(.NET Framework基础程序集) return Type.GetType($"{typeName}, mscorlib"); } } // 其他类型保持原解析逻辑 return Type.GetType($"{typeName}, {assemblyName}"); } }
修改.NET 4.8反序列化代码
在JsonSerializerSettings中配置自定义Binder:
var serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto, SerializationBinder = new CrossNetVersionBinder() // 绑定自定义Binder };
方案优势
- 无需依赖JSON格式(缩进/压缩均可处理),避免逐行修改JSON的低效操作
- 类型解析逻辑集中在Binder中,便于扩展维护
- 直接拦截类型解析流程,性能更优
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

