C# 在列表反序列化期间忽略缺少的类型
使用C# 在列表反序列化期间忽略缺少的类型,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,使用TypeNameHandling.All反序列化列表时,如果其中一个项的类型名称空间丢失(序列化后删除),将导致解析JSON中指定的类型时出现错误。 相反,我希望忽略这些项目,将其余项目抛在脑后 Error=(sender,args)=>{args.ErrorContext.Handled=true;}inJsonSerializerSettings执行我正在查找的操作,但当然会捕获所有错误 是否有一种更干净的方法可以做到这一点,可能是通过我错过的序列化程序设置?您可以使用内部的以下属性来限
TypeNameHandling.All
反序列化列表时,如果其中一个项的类型名称空间丢失(序列化后删除),将导致解析JSON中指定的类型时出现错误。
相反,我希望忽略这些项目,将其余项目抛在脑后
Error=(sender,args)=>{args.ErrorContext.Handled=true;}
inJsonSerializerSettings
执行我正在查找的操作,但当然会捕获所有错误
是否有一种更干净的方法可以做到这一点,可能是通过我错过的序列化程序设置?您可以使用内部的以下属性来限制要处理和忽略的错误类型:
- :获取导致错误的原始对象。当由于类型名称无效而无法构造列表项时,
OriginalObject
将作为列表本身
使用此属性,您可以检查OriginalObject
是否是某些T
的IList
- 。获取引发错误事件所针对的当前对象。异常会在序列化调用堆栈中冒泡,每个级别的对象都可以尝试处理错误
当
CurrentObject==ErrorContext.OriginalObject
时,您需要在最低级别处理它
- -获取实际引发的异常。您将只希望处理由引发的异常
现在,如何只检测和捕获那些由于类型名绑定失败而导致的异常?事实证明,当无法加载类型时,Json.NET会抛出一个JsonSerializationException
。但是,在许多其他情况下也可能引发相同的异常,包括格式错误的JSON文件。因此,引入一个捕获和捕获来自默认JSON绑定器的异常并将其打包为特定异常类型的:
public class JsonSerializationBinder : ISerializationBinder
{
readonly ISerializationBinder binder;
public JsonSerializationBinder(ISerializationBinder binder)
{
if (binder == null)
throw new ArgumentNullException();
this.binder = binder;
}
public Type BindToType(string assemblyName, string typeName)
{
try
{
return binder.BindToType(assemblyName, typeName);
}
catch (Exception ex)
{
throw new JsonSerializationBinderException(ex.Message, ex);
}
}
public void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
binder.BindToName(serializedType, out assemblyName, out typeName);
}
}
public class JsonSerializationBinderException : JsonSerializationException
{
public JsonSerializationBinderException() { }
public JsonSerializationBinderException(string message) : base(message) { }
public JsonSerializationBinderException(string message, Exception innerException) : base(message, innerException) { }
public JsonSerializationBinderException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
此外,在代码Json.NET的更高级别上,在另一个JsonSerializationException
中打包了JsonSerializationBinderException
,因此在决定是否处理异常时,有必要查看内部异常以查找必要类型的异常。以下设置不执行此任务:
var settings = new JsonSerializerSettings
{
SerializationBinder = new JsonSerializationBinder(new DefaultSerializationBinder()),
TypeNameHandling = TypeNameHandling.All, // Or Auto or Objects as appropriate
Error = (sender, args) =>
{
if (args.CurrentObject == args.ErrorContext.OriginalObject
&& args.ErrorContext.Error.InnerExceptionsAndSelf().OfType<JsonSerializationBinderException>().Any()
&& args.ErrorContext.OriginalObject.GetType().GetInterfaces().Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IList<>)))
{
args.ErrorContext.Handled = true;
}
},
};
var设置=新的JsonSerializerSettings
{
SerializationBinder=新的JsonSerializationBinder(新的DefaultSerializationBinder()),
TypeNameHandling=TypeNameHandling.All、//或自动或对象(视情况而定)
错误=(发送方,参数)=>
{
如果(args.CurrentObject==args.ErrorContext.OriginalObject
&&args.ErrorContext.Error.InnerExceptionsAndSelf().OfType().Any()
&&args.ErrorContext.OriginalObject.GetType().GetInterfaces().Any(t=>t.IsGenericType&&t.GetGenericTypeDefinition()==typeof(IList)))
{
args.ErrorContext.Handled=true;
}
},
};
使用扩展方法:
public static class ExceptionExtensions
{
public static IEnumerable<Exception> InnerExceptionsAndSelf(this Exception ex)
{
while (ex != null)
{
yield return ex;
ex = ex.InnerException;
}
}
}
公共静态类例外扩展
{
公共静态IEnumerable InnerExceptionsAndSelf(此异常为ex)
{
while(ex!=null)
{
收益率;
ex=ex.InnerException;
}
}
}
演示小提琴#1
请注意,ISerializationBinder
是在Json.NET中引入的。在早期版本中,包装器必须从中继承并在中设置
演示小提琴2