通过忽略错误仅反序列化有效对象

时间:2019-05-10 16:28:01

标签: c# json.net deserialization

是否存在仅解析 valid 对象并忽略 invalid 对象的内置方法(或技巧)?


非重复

问题Ignoring an invalid field when deserializing json in Json.Net 不能回答我的问题,因为它与日期时间类型的特定字段的自定义序列化程序有关。我正在寻找适用于任何属性和任何对象的通用解决方案。

换句话说,如果有什么无效的地方,那就忽略它并继续下一个条目。就json而言,文件是正确的,但是内容在某些地方可能与预期的类型不匹配。可以。


背景:文件包含许多工作流程的数组,并且单个受损条目不应破坏整个配置并实际上禁用它们。


这里有一个例子说明了我的意思。假设我有一个User数组,但是一个条目而不是string使用Name会使用数组(它可能是无效值的任意组合,例如对象数组。

我想反序列化此数组,并忽略无法反序列化的条目。这意味着预期结果应该是两个用户,即 John Tom

我尝试使用Error处理程序,但这种方式无法正常工作。它不允许我跳过错误。

void Main()
{
    var json = @"
    [
        {
            'Name': 'John',
        },
        {
            'Name': [ 'John' ]
        },
        {
            'Name': 'Tom',
        },
    ]   
    ";

    var users = JsonConvert.DeserializeObject<IEnumerable<User>>(json, new JsonSerializerSettings
    {
        Error = (sender, e) =>
        {
            e.Dump();
            e.ErrorContext.Handled = true;
            e.CurrentObject.Dump();
        }
    }).Dump();
}

class User
{
    public string Name { get; set; }
}

3 个答案:

答案 0 :(得分:2)

我这样解决了。不优雅。

var users = JsonConvert.DeserializeObject<IEnumerable<Object>>(json);

var usersList = users.ToList().Select(x => 
                {
                    try { return JsonConvert.DeserializeObject<User>(JsonConvert.SerializeObject(x)); } catch { return null; }
                }
            ).Where(x=> x != null).ToList<User>();

答案 1 :(得分:1)

关于我如何处理类似情况的一个很好的例子是,在JsonSerializerSettings / try块内专门有一组不同的catch配置。

例如:

JsonSerializerSettings jsonSetting = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore };

catch之后,可以在try部分中完成上述代码块,但未能完成JSON的解析。

您的try块在上面的那个块内可能具有正常的错误行为:

jsonSetting = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error };

提供类似的错误处理,当发生错误时,它将放入catch块中以忽略丢失的字段。

但是,这取决于您是否可以跳过数据,还是要解析所有内容。确实是视情况而定,具体取决于您的实际JSON数据集。

将其放在try / catch块上方,并根据需要使用jsonSetting进行传递,具体取决于您的特定数据集。

编辑:只是为了强调,我确实要指出,您提供的示例并不是使用该方法的完美途径,但是它确实允许我跳过为空的数组,或者在我的情况下包含无效数据。它确实取决于您的数据集,但这可能是至少追求或考虑的有用途径。

答案 2 :(得分:1)

我知道这个问题有点老,但仅供参考:

您可以使用 JsonSerializerSettings 来处理解析错误。这允许您记录发现的任何错误,在这种情况下,将此类错误标记为已处理,以便继续解析:

new JsonSerializerSettings
{
    Error = delegate(object sender, ErrorEventArgs args)
    {
        args.ErrorContext.Handled = true; 
    }
}