Подтвердить что ты не робот

Игнорировать ошибки синтаксического анализа во время разбора данных JSON.NET

У меня есть объект с предопределенной структурой данных:

public class A
{
    public string Id {get;set;}
    public bool? Enabled {get;set;}
    public int? Age {get;set;}
}

и JSON предполагается

{ "Id": "123", "Enabled": true, "Age": 23 }

Я хочу обрабатывать JSON-ошибку положительным образом, и всякий раз, когда сервер возвращает неожиданные значения для определенных типов данных, я хочу, чтобы он игнорировался, а значение по умолчанию установлено (null).

Сейчас, когда JSON частично недействителен, я получаю исключение для чтения JSON:

{ "Id": "123", "Enabled": "NotABoolValue", "Age": 23 }

И я вообще не получаю никакого объекта. Я хочу получить объект:

new A() { Id = "123", Enabled = null, Age = 23 }

и синтаксический анализ, если это возможно. Можно ли выполнить с JSON.NET?

4b9b3361

Ответ 1

Чтобы иметь возможность обрабатывать ошибки десериализации, используйте следующий код:

var a = JsonConvert.DeserializeObject<A>("-- JSON STRING --", new JsonSerializerSettings
    {
        Error = HandleDeserializationError
    });

где HandleDeserializationError - следующий метод:

public void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
{
    var currentError = errorArgs.ErrorContext.Error.Message;
    errorArgs.ErrorContext.Handled = true;
}

HandleDeserializationError будет вызываться столько раз, сколько ошибок в json-строке. Свойства, вызывающие ошибку, не будут инициализированы.

Ответ 2

То же самое, что решение Ilija, но только для ленивого/спешащего (кредит ему)

var settings = new JsonSerializerSettings { Error = (se, ev) => { ev.ErrorContext.Handled = true; } };
JsonConvert.DeserializeObject<YourType>(yourJsonStringVariable, settings);

Реквизит для варенья, чтобы сделать его еще короче =)

Ответ 3

Есть другой способ. например, если вы используете пакет nuget, который использует ньютон json и выполняет для вас десерализацию и сепарализацию. Вы можете столкнуться с этой проблемой, если пакет не обрабатывает ошибки. тогда вы не можете использовать решение выше. вам нужно обрабатывать на уровне объекта. здесь становится полезным OnErrorAttribute. Таким образом, приведенный ниже код перехватит любую ошибку для любого свойства, вы даже можете изменить его в функции OnError и назначить значения по умолчанию

public class PersonError
{
  private List<string> _roles;

  public string Name { get; set; }
  public int Age { get; set; }

  public List<string> Roles
  {
    get
    {
        if (_roles == null)
        {
            throw new Exception("Roles not loaded!");
        }

        return _roles;
    }
    set { _roles = value; }
  }

  public string Title { get; set; }

  [OnError]
  internal void OnError(StreamingContext context, ErrorContext errorContext)
  {
    errorContext.Handled = true;
  }
}

см. https://www.newtonsoft.com/json/help/html/SerializationErrorHandling.htm