简体   繁体   中英

how to exclude properties from a list of nested classes in my base class using a ContractResolver

I have two classes:

public class Customer
{
    public int ID { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int ID { get; set; }

    public int CustomerID { get; set; }
    public virtual Customer Customer { get; set; }

    public string Description { get; set; }
}

I am trying to serialize a Customer to JSON using Json.Net and a ContractResolver , excluding the Customer property from every Order . I just want to keep the Description . I don't want to use Annotation like [JsonIgnore] because I want to make the serialization different for different cases. So I do something like this:

public class CustomerContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.DeclaringType == typeof(Order) && property.PropertyName.Equals(nameof(Order.Customer)))
        {
            property.ShouldSerialize = instance => { return false; };
        }
        return property;
    }
}

Then I get a customer from the database and try to serialize it:

JsonSerializerSettings settings = new JsonSerializerSettings { ContractResolver = new CustomerContractResolver() };
string json = Newtonsoft.Json.JsonConvert.SerializeObject(customer, Formatting.Indented, settings);

The CreateProperty method of the CustomerContractResolver is called as expected for each Order in the Orders collection, but I still get an error:

Self referencing loop detected for property 'Customer' with type 'System.Data.Entity.DynamicProxies.Customer_04661D0875E326DF9B5D4D2BA503FC19E2C0EBD49A7BE593D66F67AE77F7FDBE'. Path 'Orders[0]'.

Meaning that the ShouldSerialize delegate didn't work.

Any ideas here how to exclude the Customer property from each Order ?

From the exception error message it appears you are using Entity Framework and have enabled dynamic proxies :

When creating instances of POCO entity types, the Entity Framework often creates instances of a dynamically generated derived type that acts as a proxy for the entity.

Because the objects passed in are derived, the check property.DeclaringType == typeof(Order) will fail. Instead you can follow use one of the answers from unexpected GetType() result for entity entry to check whether the underlying type is Order , for instance:

public class CustomerContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (typeof(Order).IsAssignableFrom(property.DeclaringType) && property.PropertyName.Equals(nameof(Order.Customer)))
        {
            property.ShouldSerialize = instance => { return false; };
        }
        return property;
    }
}

Checking whether the property's declaring type is assignable from Order should work whether or not dynamic proxies are being used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM