使用Json.Net时自定义异常无法从字符串正确反序列化的问题
问题原因与解决方案
第一个错误「The member ClassName could not be found」的原因
你的自定义InternalException反序列化构造函数是空实现,没有调用基类Exception的反序列化构造函数。Exception类的序列化依赖SerializationInfo中的特殊成员(如ClassName、Message、StackTrace等),空构造函数无法从info中读取这些基类必需的数据,导致反序列化时找不到成员报错。
反序列化出默认消息新异常的原因
本质和上面的问题一致:基类Exception的核心状态(原始消息、内部异常、堆栈跟踪等)没有被正确还原。反序列化器只能创建一个空壳的InternalException实例,然后填充默认的异常提示文本。
修复步骤
1. 修正自定义异常的反序列化构造函数
必须调用基类的反序列化构造函数,确保基类的所有序列化数据被正确读取:
[Serializable] public class InternalException : Exception, ISerializable { public InternalException() : base() { } public InternalException(string message) : base(message) { } public InternalException(string message, Exception innerException) : base(message, innerException) { } // 修复:调用基类的反序列化构造函数 protected InternalException(SerializationInfo info, StreamingContext context) : base(info, context) { } [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); } }
2. 确保序列化/反序列化的兼容性
如果使用Newtonsoft.Json(Json.NET),需要配置序列化器以正确处理异常类型:
- 服务端序列化时:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, // 处理多态类型(如果需要) PreserveReferencesHandling = PreserveReferencesHandling.Objects, // 避免循环引用(如果内部异常有嵌套) Formatting = Formatting.None }; string serializedEx = JsonConvert.SerializeObject(yourInternalException, settings);
- 客户端反序列化时:
var str = await resp.Content.ReadAsStringAsync(); var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; var ex = JsonConvert.DeserializeObject<InternalException>(str, settings); throw ex;
如果使用System.Text.Json,默认对Exception的支持有限,需要自定义转换器来处理Exception的所有属性,或者直接改用Newtonsoft.Json,前者配置更复杂。
3. 验证修复效果
修改完成后,无论是使用ReadAsAsync<InternalException>还是手动反序列化,都能正确还原原始异常的消息、内部异常、堆栈跟踪等信息,不会再出现找不到成员或默认消息的问题。
内容的提问来源于stack exchange,提问作者Ivan-Mark Debono
相关产品推荐
相关产品推荐

