首页 > 解决方案 > 从 Json.Net 中的 JsonReaderException 中查找无效值

问题描述

我正在运行下面的代码来故意抛出 JsonReaderException。它正确地给出了“无法将字符串转换为布尔值:aaa。路径‘活动’,第 3 行,位置 17”的异常消息。

有什么方法可以直接从 JsonReaderException 获取验证失败的值,所以我不必解析异常消息?

string json = @"{
  'Email': 'james@example.com',
  'Active': 'aaa',
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

try
{
  Account account = JsonConvert.DeserializeObject<Account>(json);
  Console.WriteLine(account.Email);
}
catch (JsonReaderException exc)
{
  // Do Something
}

标签: asp.net-corejson.netasp.net-core-2.0

解决方案


看起来有问题的值没有保存为JsonReaderException. 此值的唯一可能位置是Exception.Data字典,但是 Json.NET 不会在此处添加任何内容。

但是,通过一些工作,您可以利用 Json.NET 的序列化错误事件处理功能在引发异常时直接访问错误值。首先,定义以下辅助方法和ErrorEventArgs子类型:

public class ErrorAndValueEventArgs : Newtonsoft.Json.Serialization.ErrorEventArgs 
{
    public object ReaderValue { get; } = null;

    public ErrorAndValueEventArgs(object readerValue, object currentObject, ErrorContext errorContext) : base(currentObject, errorContext)
    {
        this.ReaderValue = readerValue;
    }
}

public static partial class JsonExtensions
{
    public static TRootObject Deserialize<TRootObject>(string json, EventHandler<ErrorAndValueEventArgs> error, JsonSerializerSettings settings = null)
    {
        using (var sr = new StringReader(json))
        using (var jsonReader = new JsonTextReader(sr))
        {
            var serializer = JsonSerializer.CreateDefault(settings);
            serializer.Error += (o, e) => error(o, new ErrorAndValueEventArgs(jsonReader.Value, e.CurrentObject, e.ErrorContext));
            return serializer.Deserialize<TRootObject>(jsonReader);
        }
    }
}

现在您将能够访问JsonReader.Value抛出异常时的值:

object errorValue = null;
try
{
    Account account = JsonExtensions.Deserialize<Account>(json, (o, e) => errorValue = e.ReaderValue);
    Console.WriteLine(account.Email);
}
catch (JsonException exc)
{
    // Do Something
    Console.WriteLine("Value at time of {0} = {1}, Data.Count = {2}.", exc.GetType().Name, errorValue, exc.Data.Count);
    // Prints Value at time of JsonReaderException = aaa, Data.Count = 0.
}

笔记:

  • 由于您必须手动创建自己的JsonTextReader,因此您需要访问 JSON 字符串(或Stream)才能使这种方法起作用。(这在您的问题中显示的示例中是正确的。)

  • JsonSerializationException Parsing中显示了用于捕获附加错误信息的类似技术 。

  • 你可能想增强ErrorAndValueEventArgs也记录JsonReader.TokenType。如果在引发异常时读取器位于容器(对象或数组)的开头,JsonReader.Value则将为 null。

演示小提琴在这里


推荐阅读