Froodooo
Froodooo

Reputation: 177

Conditionally ignore nested property when serializing object

I'm struggling with conditionally serializing a property of an object that is a property of another object itself. Consider the following class structure:

public class Message
{
    public string Content { get; set; }
    public IEnumerable<Attachment> Attachments { get; set; }
}

public class Attachment
{
    public string Base64Content { get; set; }
    public string FileName { get; set; }
}

In some scenarios I want to serialize everything in the Message class, including all Attachment objects and its properties. This can be done by using a simple JsonConvert.SerializeObject(). If I always wanted to ignore the Base64Content property, I could just add a '[JsonIgnore]' attribute on that property. However, there are some scenarios in which I want the Base64Content serialized, and in others I don't.

I though about creating a custom ContractResolver that ignores the Attachments property of the Message object. But of course, this ignores the whole list of Attachment objects and not just the Base64Content property.

Is there a way of writing a ContractResolver class that lets me ignore the Base64Content property when serializing the Message object?

Upvotes: 5

Views: 3179

Answers (1)

ctor
ctor

Reputation: 875

Just create a custom contract resolver which excludes the properties passed to it while serializing and pass the Base64Content property in it conditionally.

public class CustomPropertiesContractResolver : DefaultContractResolver
{
    private HashSet<string> _propertySet;

    public CustomPropertiesContractResolver(IEnumerable<string> propertyNames)
    {
        if (propertyNames != null)
        {
            _propertySet = new HashSet<string>(propertyNames, StringComparer.OrdinalIgnoreCase);
        }
    }

    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        List<MemberInfo> serializableMembers = null;
        var allMembers = base.GetSerializableMembers(objectType);

        if (_propertySet != null && _propertySet.Count > 0)
        {
            serializableMembers = allMembers.Where(m => !_propertySet.Contains(m.Name)).ToList();
        }
        return serializableMembers != null && serializableMembers.Count > 0 ? serializableMembers : allMembers;
    }
}

use it like:

IEnumerable<string> properties = null;
if (condition)
{
    properties = new List<string> { "Base64Content" };
}

var settings = new JsonSerializerSettings()
{
    ContractResolver = new CustomPropertiesContractResolver(properties)
};
var serializedStr = JsonConvert.SerializeObject(messages, settings);

Upvotes: 3

Related Questions