Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# json dynamic contract resolver for sub class

I am making a webrequest to pass certain properties of class to a web api so I followed the instructions in method 3 of this post and made a dynamic contract resolver:

public class DynamicContractResolver : DefaultContractResolver
{
    private IList<string> _propertiesToSerialize = null;

    public DynamicContractResolver(IList<string> propertiesToSerialize)
    {
        _propertiesToSerialize = propertiesToSerialize;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        return properties.Where(p => _propertiesToSerialize.Contains(p.PropertyName)).ToList();
    }
}

Example Usage:

var propsToSerialise = new List<string>()
{
    "body_html",
    "product_type",
    "published_scope",
    "title",
    "vendor",
    "handle"
};
DynamicContractResolver contractResolver = new DynamicContractResolver(propsToSerialise);
string json = JsonConvert.SerializeObject(product, Formatting.None, new JsonSerializerSettings { ContractResolver = contractResolver });

This works very well if the properties are part of the base class, but if the properties are part of a sub-class then it doesn't get picked up

So for example, the product has a subclass of Option and I only want the colour property of that option.

I had a look at this post on SO but it wasn't very clear about what the GetItemTypeNames() was or how to use it properly so was wondering if anyone knew how I could change the DynamicContractResolver to handle sub classes too

Example classes:

public class Product
{
    public string body_html { get; set; }
    public DateTime created_at { get; set; }
    public string handle { get; set; }
    public int id { get; set; }
    public string product_type { get; set; }
    public DateTime published_at { get; set; }
    public string published_scope { get; set; }
    public string tags { get; set; }
    public string template_suffix { get; set; }
    public string title { get; set; }
    public ProductVariant[] variants { get; set; }
    public string vendor { get; set; }
    public Option option { get; set; }
}

public class Option
{
    public string colour { get; set; } // this is the property I want to serialise
    public string size { get; set; }
    public string notes { get; set; }
}
like image 851
Pete Avatar asked May 06 '26 10:05

Pete


1 Answers

I have solved my problem by changing the CreateProperties override to:

protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
    IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
    return properties.Where(p => _propertiesToSerialize.Contains(string.Format("{0}.{1}", p.DeclaringType.Name, p.PropertyName))).ToList();
}

I could then change my propsToSerialise variable to

var propsToSerialise = new List<string>()
{
    "Product.body_html",
    "Product.product_type",
    "Product.published_scope",
    "Product.title",
    "Product.vendor",
    "Product.handle",
    "Product.option",
    "Options.colour"
}; 
like image 125
Pete Avatar answered May 08 '26 02:05

Pete