即将推出本人原译的NewtonSoft.JSON官方手册中文版完整文档(.chm格式),敬请期待!
序列化错误处理
Json.NET支持序列化和反序列化过程中的错误处理。错误处理让你能够捕获错误,并选择是否处理错误,并继续序列化,或让错误在应用程序中冒泡并抛出错误。
通过两种方法定义了错误处理:在JsonSerializer上的Error事件以及OnErrorAttribute。
- Error Event
- OnErrorAttribute
Error事件
Error事件是一个事件处理器,能在JsonSerializer上找到。每当在序列化JSON或反序列化JSON时抛出了一个异常,就引发了此事件。就像在JsonSerializer上能找到的所有设置,Error也被设置在JsonSerializerSettings,并传递给JsonConvert上的序列化方法。
序列化错误处理
List<string> errors = new List<string>();
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
'2009-09-09T00:00:00Z',
'I am not a date and will error!',
[
1
],
'1977-02-20T00:00:00Z',
null,
'2000-12-01T00:00:00Z'
]",
new JsonSerializerSettings
{
Error = delegate(object sender, ErrorEventArgs args)
{
errors.Add(args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
},
Converters = { new IsoDateTimeConverter() }
});
// 2009-09-09T00:00:00Z
// 1977-02-20T00:00:00Z
// 2000-12-01T00:00:00Z
// The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.
// Unexpected token parsing date. Expected String, got StartArray.
// Cannot convert null value to System.DateTime.
在此示例中,我们把一个JSON对象反序列化为一个DataTimes的集合。在JsonSerializerSettings上,可以给Error事件分配一个处理函数,它会记录一条消息,并标记此错误已被处理。
反序列化此JSON的结果是三条成功的反序列化日期,以及三条错误消息:一要是针对格式错误的字符串(“I am not a date and will error”),一条是针对嵌套的JSON数组,一条是针对null值,因为列表不允许可空的DateTimes。此事件处理器记录了这三条消息,Json.NET没有停止反序列化JSON,是因为错误已被标记为已处理。
Json.NET中的错误处理,有一件需要注意的事情是,未处理的错误将会冒泡,并在它的每个你对象上引发错误事件上。例如,在序列化一个对象的集合时,一个未处理的错误将被引发两次,一次是针对此对象引发,另一次发生在集合上。从而你可以在发生错误的对象上或它的任一个父级上处理错误。
父级错误处理
List<string> errors = new List<string>();
JsonSerializer serializer = new JsonSerializer();
serializer.Error += delegate(object sender, ErrorEventArgs args)
{
// only log an error once
if (args.CurrentObject == args.ErrorContext.OriginalObject)
{
errors.Add(args.ErrorContext.Error.Message);
}
};
如果你不能立即处理错误,只想针对它实施一次动作,则你可以检查ErrorEventArgs的CurrentObject是否等一OriginalObject。OriginalObject是抛出错误的对象,CurrentObject是引发事件的对象。只有在第一次针对OriginalObject引发事件时,这两者才是相等的。
OnErrorAttribute
OnErrorAttribute的作用方式很像Json.NET支持的其它.NET序列化特性。若要使用它,你只要把该特性放到方法上,并取用正确的参数:一个StreamingContext和一个ErrorContext。方法的名称是无关紧要的。
序列化错误处理特性
public class PersonError
{
private List<string> _roles;
public string Name { get; set; }
public int Age { get; set; }
public List<string> Roles
{
get
{
if (_roles == null)
{
throw new Exception("Roles not loaded!");
}
return _roles;
}
set { _roles = value; }
}
public string Title { get; set; }
[OnError]
internal void OnError(StreamingContext context, ErrorContext errorContext)
{
errorContext.Handled = true;
}
}
在此示例如,当没有设置roles时,访问Roles属性将抛出一个异常。在序列化Roles的时候,此HandleError方法将把错误设置为已处理,并让Json.NET继续序列化类。
序列化错误处理示例
PersonError person = new PersonError
{
Name = "George Michael Bluth",
Age = 16,
Roles = null,
Title = "Mister Manager"
};
string json = JsonConvert.SerializeObject(person, Formatting.Indented);
Console.WriteLine(json);
//{
// "Name": "George Michael Bluth",
// "Age": 16,
// "Title": "Mister Manager"
//}