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
  • 8,648
  • 7
  • 54
  • 101
Ben Foster
  • 33,525
  • 36
  • 167
  • 284

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,736
  • 6
  • 45
  • 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,115
  • 12
  • 28