Десериализовать только допустимые объекты, игнорируя ошибки - PullRequest
2 голосов
/ 10 мая 2019

Есть ли встроенный способ (или трюк) для анализа только допустимых объектов и игнорирования недействительных единиц?


Недубликат

Вопрос Игнорирование неверного поля при десериализации json в 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; }
}

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

Я решил таким образом.Не элегантно.

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 голос
/ 10 мая 2019

Хорошим примером того, как я подошел к аналогичной ситуации, может быть набор различных конфигураций 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 для передачи по мере необходимости, в зависимости от вашегоконкретный набор данных.

РЕДАКТИРОВАТЬ: Просто для акцента, я хочу отметить, что образец, который вы предоставили, не является совершенным маршрутом для подхода с использованием этого метода, но он позволил мнепропустить массивы, которые были нулевыми или имели недопустимые данные в моем случае .Это действительно зависит от вашего набора данных, но это может быть полезным способом, по крайней мере, продолжить или рассмотреть.

...