您可以在
SerializationErrorCallback
中使用以下
ErrorContext
属性来限制要处理和忽略的错误类型:
现在,如何仅检测和捕获由于类型名称绑定失败而引起的异常?事实证明,Json.NET的DefaultSerializationBinder
在无法加载类型时会引发JsonSerializationException
。然而,相同的异常也可能在许多其他情况下引发,包括格式不正确的JSON文件。因此,引入一个装饰器ISerializationBinder
来捕获并捕获默认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将JsonSerializationBinderException
包装在另一个JsonSerializationException
中,因此在决定是否处理异常时,需要查看内部异常中是否有必要类型的异常。以下设置可以完成此操作:
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;
}
},
};
使用扩展方法:
public static class ExceptionExtensions
{
public static IEnumerable<Exception> InnerExceptionsAndSelf(this Exception ex)
{
while (ex != null)
{
yield return ex;
ex = ex.InnerException;
}
}
}
这里是演示fiddle #1 链接。
请注意,ISerializationBinder
是在Json.NET 10.0.1中引入的。 在早期版本中,您的包装器必须继承自SerializationBinder
并在JsonSerializerSettings.Binder
中设置。
这里是演示fiddle #2 链接。