• Json.Net学习笔记(九) 异常处理


    Json.Net支持在序列化和反序列化的过程中进行异常处理。异常处理让您捕获一个异常,您可以选择是否处理它,继续序列化或者让异常抛给上一层,在你的应用程序中被抛出。

    异常处理通过两个方法来定义:the Error event on JsonSerializer 和 OnErrorAttribute

    >Error Event

      error event是一个建立在JsonSerializer 上的异常处理.当序列化或者反序列化JSON时,任何有异常抛出的情况error event都会被触发.就像建立在JsonSerializer上的所有设置一样,它也可以在JsonSerializerSettings 上进行设置从而传递给JsonConvert的序列化方法.

    示例:

     List<string> errors = new List<string>();
                List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
                      ""2010-12-19T00:00:00Z"",
                      ""I am not a date and will error!"",
                      [
                        1
                      ],
                      ""2011-01-01T00:00:00Z"",
                      null,
                      ""2010-12-25T00:00:00Z""
                      ]", new JsonSerializerSettings()
                            {
                                Error = delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
                                {
                                    errors.Add(e.ErrorContext.Error.Message);
                                    e.ErrorContext.Handled = true;
                                },
                                Converters = { new IsoDateTimeConverter() }
                            });
                foreach (DateTime t in c)
                {
                    Console.WriteLine(t.ToString());
                }
                //2010-12-19 00:00:00
                //2011-01-01 00:00:00
                //2010-12-25 00:00:00
                foreach (string err in errors)
                {
                    Console.WriteLine(err);
                }
                //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数组反序列化为一个DateTime的集合,在JsonSerializerSettings中有一个hander被赋值成了error event ,它用来记录error message,并标记这个error为已处理(handled).

    反序列化JSON的结果是三个被成功反序列化的日期和三个error messages:一个是不正确的格式,"I am not a date and will error!",一个是嵌套了JSON数组,最后一个是null值,因为定义的list不允许有可空类型的DateTime.这个事件处理已经记录了这些信息,Json.Net在序列化时继续进行(没有因为异常而停止),因为这些错误已经被标记为已处理。

       值得注意的是,在Json.Net进行异常处理时,没有处理的异常将会被抛到上一层,并在它的每个parent触发事件,例如:在序列化若干对象的集合时,一个未处理的异常将被触发两次,首先在对象上,然后在集合上。这样就会让您在处理异常的时候,选择在它发生的地方,或者是它的一个parent上。


     JsonSerializer serializer = new JsonSerializer();
                serializer.Error += delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
                {
                    // only log an error once
                    if (e.CurrentObject == e.ErrorContext.OriginalObject)
                        errors.Add(e.ErrorContext.Error.Message);
                };

    如果您不是立即处理一个异常,仅仅是想针对它完成一次操作,您可以验证一下ErrorEventArg's CurrentObject是否等于OriginalObject.OriginalObject是抛出异常的对象,CurrentObject是事件被触发的对象.他们只会在第一次(事件被OriginalObject触发时)相等.

    >OnErrorAttribute

     OnErrorAttribute的工作方式非常像其他Json.Net支持的.NET serialization attributes ,简单地把它标记在带有正确参数(一个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属性时,异常处理的方法将设置error为handled,从而允许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"
                }

  • 相关阅读:
    11-3 多道批处理系统
    URAL 1108 简单的树形dp背包问题
    POJ 2486 树形dp
    HDU 2242 连通分量缩点+树形dp
    POJ 3140 Contestants Division
    POJ 2378 Tree Cutting
    ZOJ 3201 树形背包问题
    POJ 1655 Balancing Act && POJ 3107 Godfather
    COJ 1351 Tree Counting 动态规划
    codeforces 219D 树形dp
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/2251124.html
Copyright © 2020-2023  润新知