Reputation: 141
I have to serialize derived class, but I need all data it contains (including private fields and base class ones).
I'd like to use [Datacontract]
as below.
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace ConsoleApplication1
{
class Program
{
[DataContract]
class Base
{
public Base(int fieldValue)
{
_field = fieldValue;
}
[DataMember]
private int _field;
}
class Derived : Base
{
public Derived(int fieldValue) : base(fieldValue)
{
}
}
public static void Main(string[] args)
{
var derived = new Derived(10);
var serialized = JsonConvert.SerializeObject(derived);
Console.WriteLine(serialized);
}
}
}
But there are too much legacy classes to modify, so I followed the question and wrote Contract resolver
public class MyContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = type
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(p => p.CanRead && p.CanWrite)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.Distinct(JsonPropertyComparer.Instance)
.ToList();
foreach (var property in properties)
{
var ignored = ShouldPropertyBeIgnored(property);
property.Ignored = ignored;
property.Readable = !ignored;
property.Writable = !ignored;
}
return properties;
}
// Actualy, contains some logic
private bool ShouldPropertyBeIgnored(JsonProperty property) => false;
}
Unfortunately, it does not serialise properties of base types
Upvotes: 0
Views: 368
Reputation: 141
As user2864740 mentioned, private properties of base types are not inherited (and they are not polymorphic), and thus currentType.GetProperties(..) doesn’t include them.
So, I iterated through .BaseType
as there.
It fixed my trouble. Reproducible code example is below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace DerivedSerialization
{
internal class MyContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = GetJsonProperties(type, memberSerialization);
foreach (var property in properties)
{
property.Ignored = false;
property.Readable = true;
property.Writable = true;
}
return properties;
}
private IList<JsonProperty> GetJsonProperties(Type type, MemberSerialization memberSerialization)
{
var properties = type
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(p => p.CanRead && p.CanWrite)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)));
if (type.BaseType == null)
return properties.Distinct(new JsonPropertyComparer()).ToList();
return properties.Union(GetJsonProperties(type.BaseType, memberSerialization))
.Distinct(new JsonPropertyComparer())
.ToList();
}
}
#region JsonPropertyComparer
internal class JsonPropertyComparer : IEqualityComparer<JsonProperty>
{
public bool Equals(JsonProperty left, JsonProperty right)
{
if (ReferenceEquals(left, right)) return true;
if (left == null || right == null) return false;
return left.PropertyName?.Equals(right.PropertyName) ?? right.PropertyName == null;
}
public int GetHashCode(JsonProperty obj)
{
return obj.PropertyName?.GetHashCode() ?? 0;
}
}
#endregion
internal class Program
{
class Base
{
public Base(int fieldValue)
{
_field = fieldValue;
}
private int _field;
}
class Derived : Base
{
public Derived(int fieldValue) : base(fieldValue)
{
}
}
public static void Main(string[] args)
{
var derived = new Derived(10);
var jsonSettings = new JsonSerializerSettings { ContractResolver = new MyContractResolver() };
var serialized = JsonConvert.SerializeObject(derived, jsonSettings);
Console.WriteLine(serialized);
}
}
}
Upvotes: 1