c# - JsonSerializationException 解析

标签 c# json.net

我正在尝试用一些优雅的异常处理来包装我的应用程序。当我的应用无法反序列化 JSON 时,我得到一个 JsonSerializationException,它有一个如下所示的消息:

Error converting value "[IncorrectDataType]" to type 'ApexFramework.Enums+DataTypes'. Path 'Layout[0].ElementContainer[0].ContainerDatatype', line 12, position 58.

从这个异常消息中,我有兴趣以干净的方式捕获和呈现以下内容:

  • 我需要 Layout[] 中元素容器的索引(在上例中为 0)
  • 我需要 ElementContainer[] 中 ContainerDataType 的索引(在上例中为 0)

我翻了一下

JsonSerializationException

对象,没有任何东西是我可以轻松捕获的,所以:

谁能确认无法使用 JsonSerializationException 以干净的方式获取我需要的信息?

如果没有,谁能帮我想出最优雅、最有效的方法来从异常堆栈中获取我需要的信息?

最佳答案

您可以使用 Json.NET 的 serialization error event handling以更有用的格式获取有关异常的信息的功能。

当反序列化期间发生异常时,Json.NET 会在对象层次结构的每个级别捕获并重新抛出它,让每个对象都有机会使用 OnError 处理异常。方法。虽然您不想处理异常,但您可以利用它通过 ErrorEventArgs 中提供的信息记录有关异常发生位置的详细信息。传给了JsonSerializerSettings.Error事件处理程序。例如,以下代码捕获并报告 path发生异常时,member导致异常,以及 objects 的堆栈在遇到错误时被反序列化:

static bool TryDeserialize<TRootObject>(string jsonString, out TRootObject root)
{
    var errorStack = new Stack<Newtonsoft.Json.Serialization.ErrorEventArgs>();
    var settings = new JsonSerializerSettings
    {
        Converters = { new StringEnumConverter() },
        Error = (o, e) => errorStack.Push(e)
    };
    try
    {
        root = JsonConvert.DeserializeObject<TRootObject>(jsonString, settings);
        return true;
    }
    catch (JsonException ex)
    {
        var last = errorStack.Last();
        var member = last.ErrorContext.Member;
        var path = last.ErrorContext.Path;
        var objectsStack = String.Join(", ", errorStack
                                       .Where(e => e.CurrentObject != null)
                                       .Select(e => e.CurrentObject.ToString()));

        Console.WriteLine("Exception parsing JSON: ");
        Console.WriteLine(ex.Message);
        Console.WriteLine("Error context details: ");
        Console.WriteLine("   Path: {0}\n   Member: {1}\n   Object stack = {{{2}}}", 
                          path, member, objectsStack);
        root = default(TRootObject);
        return false;
    }
}

然后,如果我尝试将 JSON 反序列化为您的问题所隐含的数据模型,我会收到以下错误消息:

Exception parsing JSON: 
Error converting value "[IncorrectDataType]" to type 'DataTypes'. Path 'Layout[0].ElementContainer[0].ContainerDatatype', line 6, position 56.
Error context details: 
   Path: Layout[0].ElementContainer[0].ContainerDatatype
   Member: ContainerDatatype
   Object stack = {RootObject, System.Collections.Generic.List`1[Layout], Layout, System.Collections.Generic.List`1[ElementContainer], ElementContainer}

如您所见,您需要的信息更清晰可用,因此您将不再需要解析异常消息。您仍然需要解析异常路径以提取索引,但是路径语法是标准的 JSONPath syntax所以是明确定义的。您可以在任何预先存在的 JSONPath 解析器(包括 Json.NET 自己的 JPath)上为您的路径解析代码建模。 .

注意事项:

  • 我不特别推荐处理异常并继续,因为据报道 Json.NET 中的错误处理是 "very flaky"由 Newtonsoft 提供。

示例工作 .Net fiddle here .

关于c# - JsonSerializationException 解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53130847/

相关文章:

c# - 无法连接任何指定的 mysql 主机

c# - 强制 Etag 检查 Blob 创建

c# - 将字符串拆分为单个字符的字符串数组

c# - 如何实例化新的结构对象?

c# - 比较两个相同结构的任意 JToken-s

c# - 将 JsonDictionary 属性应用于字典

c# - 为json数组的所有对象添加属性

c# - 使用 Newtonsoft C# 从 json 转换为 Enum

c# - 线程安全类是否应该在其构造函数的末尾设置内存屏障?

c# - 反序列化 PSON 文件