在JSON.NET数据解析期间忽略解析错误

Ale*_*akh 57 error-handling json json.net deserialization

我有一个预定义数据结构的对象:

public class A
{
    public string Id {get;set;}
    public bool? Enabled {get;set;}
    public int? Age {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

和JSON应该是

{ "Id": "123", "Enabled": true, "Age": 23 }
Run Code Online (Sandbox Code Playgroud)

我想以积极的方式处理JSON错误,并且每当服务器返回已定义数据类型的意外值时,我希望它被忽略并且默认值被设置(null).

现在,当JSON部分无效时,我收到JSON读卡器异常:

{ "Id": "123", "Enabled": "NotABoolValue", "Age": 23 }
Run Code Online (Sandbox Code Playgroud)

而且我根本没有任何对象.我想要的是获得一个对象:

new A() { Id = "123", Enabled = null, Age = 23 }
Run Code Online (Sandbox Code Playgroud)

并在可能的情况下解析警告.是否可以使用JSON.NET完成?

Ili*_*mov 94

为了能够处理反序列化错误,请使用以下代码:

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

HandleDeserializationError以下方法在哪里:

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

由于HandleDeserializationErrorjson字符串中存在错误,因此将多次调用.导致错误的属性不会被初始化.

  • 请注意,ErrorEventArgs是Newtonsoft.Json.Serialization.ErrorEventArgs而不是System.IO.ErrorEventArgs. (27认同)
  • 您如何忽略集合中的单个错误元素?使用这种方法,Json.NET似乎忽略了整个集合,而不仅仅是错误的元素。 (3认同)
  • 根据我的经验,仅当 json 字符串格式不正确时,JSON.NET 才会忽略整个集合,如果 json 字符串格式正确但类型不匹配,它将忽略单个元素的错误属性。(例如,您正在尝试将字符串反序列化为整数属性) (2认同)
  • @IlijaDimov 有趣。就我而言,元素子树中的某处缺少属性。但 Json.NET 似乎并没有在该位置抛出错误,而是在父集合处开始错误冒泡,如果我在那里执行 `Handled = true` 操作,整个集合就会设置为 null :/。 (2认同)

Gas*_*a79 9

与Ilija的解决方案相同,但是对于懒惰/匆忙的一个oneliner(荣誉归于他)

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

Jam的道具让它更短=)

  • 甚至更短的`Error =(se,ev)=> ev.ErrorContext.Handled = true` (4认同)

bat*_*aci 5

还有另一种方法。例如,如果您使用的是使用 newton json 并为您进行反序列化和序列化的 nuget 包。如果包未处理错误,您可能会遇到此问题。那么你不能使用上面的解决方案。您需要在对象级别处理。这里变得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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我尝试了这段代码,但尽管“Handled=true”,库还是抛出异常。漏洞? (3认同)