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

How to ignore a property declared as Object based on the value's actual type when serializing with a custom ContractResolver

我有一个 class 这样的:

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;
    }
}

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

property.PropertyType 将 return 属性 的已声明(编译时)类型,此处始终为 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;
}

Fiddle: https://dotnetfiddle.net/2A2KMH