从 Json.Net 中的 JsonReaderException 中查找无效值
Find invalid values from JsonReaderException in Json.Net
我运行下面的代码故意抛出JsonReaderException。它正确地给出了 "Could not convert string to boolean: aaa. Path 'Active', line 3, position 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
}
似乎违规值未在 JsonReaderException
. The only possible location for this value would be the Exception.Data
字典中保存为 属性,但是 Json.NET 未在此处添加任何内容。
但是,通过一些工作,您可以利用 Json.NET 的 serialization error event handling functionality to directly access the bad value at the time the exception is thrown. First, define the following helper method and 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
。如果在抛出异常时 reader 位于容器(对象或数组)的开头,则 JsonReader.Value
将为空。
演示 fiddle here.
我运行下面的代码故意抛出JsonReaderException。它正确地给出了 "Could not convert string to boolean: aaa. Path 'Active', line 3, position 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
}
似乎违规值未在 JsonReaderException
. The only possible location for this value would be the Exception.Data
字典中保存为 属性,但是 Json.NET 未在此处添加任何内容。
但是,通过一些工作,您可以利用 Json.NET 的 serialization error event handling functionality to directly access the bad value at the time the exception is thrown. First, define the following helper method and 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
。如果在抛出异常时 reader 位于容器(对象或数组)的开头,则JsonReader.Value
将为空。
演示 fiddle here.