2

Is there some non-attribute-based method of ignoring all properties that don't have a corresponding constructor parameter when serializing? For example, when serializing this class, property Combo should be ignored. A round-trip serialization/deserialization of an instance of MyClass doesn't require Combo to be serialized. Ideally I could use some out-of-the-box setting.

public class MyClass
{
    public MyClass(int myInt, string myString)
    {
        this.MyInt = myInt;
        this.MyString = myString;
    }

    public int MyInt { get; }

    public string MyString { get; }

    public string Combo => this.MyInt + this.MyString;
}
Suraj
  • 35,905
  • 47
  • 139
  • 250
  • if parameters name in the constructor are the same as attributes names, I think that reflection may help you to get the list of properties that should be serialized. Then you can use this simple to create the non-attribute-based method http://stackoverflow.com/questions/9377414/excluding-some-properties-during-serialization-without-changing-the-original-cla – AnotherGeek Apr 28 '16 at 13:35

1 Answers1

2

You can do this with a custom IContractResolver:

public class ConstructorPropertiesOnlyContractResolver : DefaultContractResolver
{
    readonly bool serializeAllWritableProperties;

    public ConstructorPropertiesOnlyContractResolver(bool serializeAllWritableProperties)
        : base()
    {
        this.serializeAllWritableProperties = serializeAllWritableProperties;
    }

    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        var contract = base.CreateObjectContract(objectType);

        if (contract.CreatorParameters.Count > 0)
        {
            foreach (var property in contract.Properties)
            {
                if (contract.CreatorParameters.GetClosestMatchProperty(property.PropertyName) == null)
                {
                    if (!serializeAllWritableProperties || !property.Writable)
                        property.Readable = false;
                }
            }
        }

        return contract;
    }
}

Then use it like:

var settings = new JsonSerializerSettings { ContractResolver = new ConstructorPropertiesOnlyContractResolver(false) };
var json = JsonConvert.SerializeObject(myClass, Formatting.Indented, settings );

Pass true for serializeAllWritableProperties if you also want to serialize read/write properties that are not included in the constructor parameter list, e.g. AnUnrelatedReadWriteProperty in:

public class MyClass
{
    public MyClass(int myInt, string myString)
    {
        this.MyInt = myInt;
        this.MyString = myString;
    }

    public int MyInt { get; private set; }

    public string MyString { get; private set; }

    public string Combo { get { return this.MyInt + this.MyString; } }

    public string AnUnrelatedReadWriteProperty { get; set; }
}

Note you may want to cache your contract resolver for best performance.

dbc
  • 104,963
  • 20
  • 228
  • 340