Deserialize only valid objects by ignoring errors

佐手、 提交于 2020-07-09 04:39:13

问题


Is there a built-in way (or a trick) for parsing only valid objects and ignoring invalid ones?


Not a duplicate

The question Ignoring an invalid field when deserializing json in Json.Net does not answer my question because it's about a custom serializer for a very specific field of date-time type. I'm seeking a generic solution working for any property and any object.

In other words if anything is invalid, just ignore it and contintue to the next entry. As far as json is concerned, the file is correct but the content might not match the expected types in some places. It can by anything.


Background: The file contains an array of many workflows and a single damaged entry should not break the entire configuration and virtually disable them all.


Here's an example demonstrating what I mean. Let's say I have an array of Users but one entry instead of using a string for the Name uses an array (it might by any combination of invalid values, like an object where an array is expected.

I'd like to deserialize this array and ignore entries that couldn't be deserialized. This means that the expected result should be two users, John & Tom.

I tried to use the Error handler but it does not work this way. It doesn't allow me to skip the errors.

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; }
}

回答1:


I solved this way. Not elegant.

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>();



回答2:


A good example of how I approached a similar situation would be to have a set of different JsonSerializerSettings configuration specifically within a try/catch block.

For example:

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

The above code block could be done within the catch section after you try and failed to complete the parse of the JSON.

Your try block could have normal error behavior inside that block above:

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

Provides similar error handling, and when that errors, it drops into the catch block to ignore the missing fields.

However, that depends on whether you're OK with skipping data, or if you want to parse everything. It really is a case-by-case basis dependent on your actual JSON dataset.

Placing this above the try/catch blocks, and using jsonSetting to pass along as needed, depending on your specific dataset.

EDIT: Just for emphasis, I do want to point out that the sample you provided isn't a perfect route to approach using this method, but it did allow me to skip arrays that were null, or had invalid data in my case. It really depends on your dataset, but this may be a useful route to at least pursue or consider.



来源:https://stackoverflow.com/questions/56081519/deserialize-only-valid-objects-by-ignoring-errors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!