Given a data model:
[DataContract]
public class Parent
{
[DataMember]
public IEnumerable Children { get; set; }
}
[DataContract]
publ
I use a custom Contract Resolver to limit which of my properties to serialize. This might point you in the right direction.
e.g.
/// <summary>
/// json.net serializes ALL properties of a class by default
/// this class will tell json.net to only serialize properties if they MATCH
/// the list of valid columns passed through the querystring to criteria object
/// </summary>
public class CriteriaContractResolver<T> : DefaultContractResolver
{
List<string> _properties;
public CriteriaContractResolver(List<string> properties)
{
_properties = properties
}
protected override IList<JsonProperty> CreateProperties(
JsonObjectContract contract)
{
IList<JsonProperty> filtered = new List<JsonProperty>();
foreach (JsonProperty p in base.CreateProperties(contract))
if(_properties.Contains(p.PropertyName))
filtered.Add(p);
return filtered;
}
}
In the override IList function, you could use reflection to populate the list with only the parent properties perhaps.
Contract resolver is applied to your json.net serializer. This example is from an asp.net mvc app.
JsonNetResult result = new JsonNetResult();
result.Formatting = Formatting.Indented;
result.SerializerSettings.ContractResolver =
new CriteriaContractResolver<T>(Criteria);
I have not used JSON.Net in particular so not positive this will help you. If JSON.Net derives itself from the .Net serialization system then you should be able to add the [NonSerialized] attribute to your properties you do now wish to be serialized in the base class. When you call the serialize methods on the base class, serialization should then skip those elements.
I had the exact same problem and looked up how to build the ContractResolver I was actually looking for and that better answer this question. This only serializes the Properties of the Type T you actually want to serialize, but with this example you can also easily build similar approaches:
public class TypeOnlyContractResolver<T> : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = instance => property.DeclaringType == typeof (T);
return property;
}
}
Check out the answers in this similar thread, particularly the IgnorableSerializerContractResolver in my answer and the nicer lambda version
Usage:
var jsonResolver = new IgnorableSerializerContractResolver();
// ignore single property
jsonResolver.Ignore(typeof(Company), "WebSites");
// ignore single datatype
jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject));
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };
Having encountered a similar problem, this is the ContractResolver
I came up with:
public class StrictTypeContractResolver : DefaultContractResolver
{
private readonly Type _targetType;
public StrictTypeContractResolver( Type targetType ) => _targetType = targetType;
protected override IList<JsonProperty> CreateProperties( Type type, MemberSerialization memberSerialization )
=> base.CreateProperties
(
_targetType.IsAssignableFrom( type ) ? _targetType : type,
memberSerialization
);
}
It cuts off only the properties of targetType
's descendants, without affecting the properties of its base classes or of other types that targetType
's properties might reference. Which, depending on your needs, may or may not be an improvement over the other answers provided here at the time.
Haven't compared performance implications, but this is a working solution as well, and works with nested/referenced objects as well.
Derived d = new Derived();
string jsonStringD = JsonConvert.SerializeObject(d);
Base b = new Base();
JsonConvert.PopulateObject(jsonStringD, b);
string jsonStringB = JsonConvert.SerializeObject(b);