json.Net +处理基于属性的反序列化错误

本文关键字:属性 反序列化 错误 Net 处理 于属性 json | 更新日期: 2023-09-27 18:16:18

我有以下的类结构

public class Parent
{
    public int SomeProperty { get; set; }
    [IgnoreDeserializationErrors] // This attribute can be here
    public FirstLevel FirstLevelProperty { get; set; }
}
public class FirstLevel
{
    public int AnotherProperty { get; set; }
    [IgnoreDeserializationErrors] // Or this can be here
    public SecondLevel SecondLevelProperty { get; set; }
}
public class SecondLevel
{
    public int OneMoreProperty { get; set; }
    [IgnoreDeserializationErrors] //Or Here
    public string YetAnotherProperty { get; set; }
}

And this Attribute:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IgnoreDeserializationErrorsAttribute : Attribute
{
}

如何告诉Json。忽略所有具有IgnoreDeserializationErrorsAttribute属性的属性的错误。

我试着

var deserialized = JsonConvert.Deserialize<Parent>(someJson, new JsonSerializerSettings
        {
            Error = (s, e) => { 
                bool attributeDefined = true;//TODO: How do I get the properties attributes here.
                if (attributeDefined)
                {
                    e.ErrorContext.Handled = true 
                }
            }
        });

但是我无法在委托中填充attributeDefined变量。

这在错误处理程序中是可能的吗?或者我必须创建一个自定义转换器

json.Net +处理基于属性的反序列化错误

有一个内置的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;
    }
}

查看序列化错误处理文章了解更多信息。

为了简单起见,让我们使用以下类:

public class Parent
{
    public int SomeProperty { get; set; }
    public FirstLevel FirstLevelProperty { get; set; }
}
public class FirstLevel
{
    public int AnotherProperty { get; set; }
    public SecondLevel SecondLevelProperty { get; set; }
}
public class SecondLevel
{
    public int OneMoreProperty { get; set; }
    [IgnoreDeserializationErrors]
    public int YetAnotherProperty { get; set; }
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IgnoreDeserializationErrorsAttribute : Attribute
{
}

您可以注意到,我将YetAnotherProperty的类型更改为int,并且只有该属性使用IgnoreDeserializationErrorsAttribute进行装饰

var someJson = "{'"SomeProperty'": 3, '"FirstLevelProperty'": {'"AnotherProperty'": 35, '"SecondLevelProperty'": {'"OneMoreProperty'": 359, '"YetAnotherProperty'": '"test'"}}}";
var deserialized = JsonConvert.DeserializeObject<Parent>(someJson, new JsonSerializerSettings
{
    Error = (s, e) =>
    {
        bool attributeDefined = false;
        if (e.CurrentObject == null) return;
        PropertyInfo property = e.CurrentObject.GetType().GetProperty(e.ErrorContext.Member.ToString());
        if (property == null) return;
        var attr = property.GetCustomAttribute(typeof (IgnoreDeserializationErrorsAttribute));
        if (attr != null) attributeDefined = true;
        if (attributeDefined) e.ErrorContext.Handled = true;
    }
});

错误处理程序中的代码读取导致错误的属性,检查该属性是否用IgnoreDeserializationErrorsAttribute装饰,并相应地设置ErrorContext的Handled属性。

示例:https://dotnetfiddle.net/zIj5RN