JSON.Net: Force serialization of all private fields and all fields in sub-classes
This should work:
var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver() };
var json = JsonConvert.SerializeObject(obj, settings);
public class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
@L.B's answer is great. But ... it requires .NET 3.5 or above.
For those of us stuck with 2.0 ...
public class ForceJSONSerializePrivatesResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
List<Newtonsoft.Json.Serialization.JsonProperty> jsonProps = new List<Newtonsoft.Json.Serialization.JsonProperty>();
foreach( var prop in props )
{
jsonProps.Add( base.CreateProperty(prop, memberSerialization));
}
foreach( var field in type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) )
{
jsonProps.Add ( base.CreateProperty( field, memberSerialization ) );
}
jsonProps.ForEach(p => { p.Writable = true; p.Readable = true; });
return jsonProps;
}
}
...seems to work.
Awesome thanks @L.B. Here's a full implementation in a .linq script in case anyone wants to test with private subclasses - e.g. See A has private subclass B.
void Main()
{
var a = A.Test();
SerialiseAllFields.Dump(a);
}
class A
{
private int PrivField1;
private int PrivProp1 { get; set; }
private B PrivSubClassField1;
public static A Test()
{
return new A { PrivField1 = 1, PrivProp1 = 2, PrivSubClassField1 = B.Test() };
}
}
class B
{
private int PrivField1;
private int PrivProp1 { get; set; }
public static B Test()
{
return new B { PrivField1 = 3, PrivProp1 = 4 };
}
}
// Define other methods and classes here
public static class SerialiseAllFields
{
public static void Dump(object o, bool indented = true)
{
var settings = new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = new AllFieldsContractResolver() };
if (indented)
{
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
}
Newtonsoft.Json.JsonConvert.SerializeObject(o, settings).Dump();
}
}
public class AllFieldsContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
{
var props = type
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
The interesting thing is that the backing fields for the properties are also serialized i.e. output is:
{
"PrivProp1": 2,
"PrivField1": 1,
"<PrivProp1>k__BackingField": 2,
"PrivSubClassField1": {
"PrivProp1": 4,
"PrivField1": 3,
"<PrivProp1>k__BackingField": 4
}
}