16

How can I customize Json.NET to serialize private members and NOT serialize public readonly properties (without using attributes).

I've had a stab around at creating a custom IContractResolver but am a bit lost.

shytikov
  • 9,155
  • 8
  • 56
  • 103
Ben Foster
  • 34,340
  • 40
  • 176
  • 285

2 Answers2

12

For a partial answer, messing with DefaultContractResolver.DefaultMembersSearchFlags can get it to include private things:

Newtonsoft.Json.JsonSerializerSettings jss = new Newtonsoft.Json.JsonSerializerSettings();

if (includePrivateMembers)
{
    Newtonsoft.Json.Serialization.DefaultContractResolver dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
    dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
    jss.ContractResolver = dcr;
}

return Newtonsoft.Json.JsonConvert.SerializeObject(o, jss);

Seems to work on a lot of objects, though with some this seems to generate a CLR exception.

Chris
  • 9,986
  • 8
  • 48
  • 56
  • Worked for me. +1. How can I now specify what properties to exclude? A regex option would be even better. – Mukus Nov 22 '13 at 02:33
4

In response to Chris' answer, the DefaultMemberSearchFlags property on DefaultContractResolver was deprecated as of version 6. Despite of what the deprecation message says, I believe you'll need to overwrite the CreateProperties method, too, like L.B explains.

This method gives you full control, including excluding readonly properties:

class PrivateContractResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
        MemberInfo[] fields = objectType.GetFields(flags);
        return fields
            .Concat(objectType.GetProperties(flags).Where(propInfo => propInfo.CanWrite))
            .ToList();
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
           return base.CreateProperties(type, MemberSerialization.Fields);
    }           
}
Community
  • 1
  • 1
tm1
  • 1,180
  • 12
  • 28