在使用自定义ContractResolver进行序列化时,如何根据值的实际类型忽略声明为Object的属性

时间:2016-11-23 03:56:25

标签: json.net ravendb

我有一个这样的课程:

class Test
{
    public object Obj { get; set; }
}

有时,Obj具有非可序列化类型的值,例如:byte[]SqlDataReader

当值类型为ContractResolver时,我尝试使自定义byte[]忽略该属性。但它不起作用:属性类型仍然是Object,而不是byte[]

public class AutoIgnoreComplexTypesContractResolver : DefaultContractResolver
{
    private static readonly List<Type> IgnoredTypes = new List<Type>()
    {
        typeof(byte[]),
        typeof(SqlDataReader)
    };

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        var propertyType = property.PropertyType.GetUnderlyingType();

        if (IgnoredTypes.Contains(propertyType))
        {
            property.ShouldSerialize = instance => false;
        }
        else
        {
            property.ShouldSerialize = instance => true;
        }
        return property;
    }
}

你能帮助我获得真正的价值类型并忽略它吗?

1 个答案:

答案 0 :(得分:2)

property.PropertyType将返回属性的声明(编译时)类型,此处始终为object。如果您希望根据属性值的实际运行时类型决定序列化,则需要使用反射从instance获取值,然后检查其类型。
请尝试这样:

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
    var property = base.CreateProperty(member, memberSerialization);

    if (property.PropertyType == typeof(object))
    {
        property.ShouldSerialize = instance =>
        {
            PropertyInfo pi = member as PropertyInfo;
            object propertyValue = (pi != null) ? pi.GetValue(instance) : null;
            return propertyValue != null && !IgnoredTypes.Contains(propertyValue.GetType());
        };
    }
    else if (IgnoredTypes.Contains(property.PropertyType))
    {
        property.ShouldSerialize = instance => false;
    }

    return property;
}

小提琴:https://dotnetfiddle.net/2A2KMH