2

This may seem silly, but It was the only way I can phrase it.

What I am trying to do is serialise an object and its data. The object is inheriting a large BaseObject class. I don't wan't any of the information from the inherited object to appear in the Json object, however I cannot access, or change the BaseObject class.

The class is used for pretty much all objects and there are other times where I serialize Json where many of the properties are needed, so adding [JsonIgnore] to the class wouldn't make it work.

I was wondering if there was another way to do it in terms of using JsonSerializerSettings, or any other way of doing it.

Any help would be appreciated.

Sam Bunting
  • 793
  • 1
  • 16
  • 36
  • Try to override ShouldSerializeEnvelope() : `public override bool ShouldSerializeEnvelope() { return false; }` – KamikyIT Jul 10 '17 at 11:25
  • Duplicate of https://stackoverflow.com/questions/31104335/ignore-base-class-properties-in-json-net-serialization ?? Note that JSON.Net == Newtonsoft.Json – Dan Rayson Jul 10 '17 at 11:30

2 Answers2

6

Yes, this is possible using a custom contract resolver.

Something like this:

public class BaseClass
{
    public string BaseClassProperty { get; set; }
}

public class ChildClass: BaseClass
{
    public string ChildClassProperty { get; set; }
}

public class CustomContractResolver : DefaultContractResolver
{

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        var propsToIgnore = typeof(BaseClass).GetProperties().Select(p => p.Name).ToList();

        properties =
            properties.Where(p => !propsToIgnore.Contains( p.PropertyName) ).ToList();

        return properties;
    }
}

so then this:

var test = new ChildClass { BaseClassProperty = "a", ChildClassProperty = "b" };

var searialisedString = JsonConvert.SerializeObject(test, new JsonSerializerSettings
{
    ContractResolver = new CustomContractResolver()
});

Console.WriteLine(searialisedString);

produces the expected output:

{"ChildClassProperty":"b"}
Stewart_R
  • 13,008
  • 8
  • 52
  • 95
  • That has seemed to have worked! I didn't even need to mess around with the BaseObject class. Thank you for your help. – Sam Bunting Jul 10 '17 at 12:13
1

I would suggest not fiddling with your base object or serializer which may be being used elsewhere and could have odd effects.

There is a pattern for doing this sort of thing where you want to mask or aggregate data between different areas or domains:

Data transfer object

I would suggest looking into this. It allows you to have a more fine grained set of models on your API that don't expose all of your code and you can even expose them in a contract through nuget or similar with a small DLL with minimal dependencies.

Means you may have code that looks a bit like

public static class MyObjectDtoMapper {
    public static Contract.MyDto Map(SpecificDomain.MyObject obj) {
        return new MyDto {
            OnlyPropertyWanted = obj.Property
        };
    }
}

var dtoMappedObject = MyObjectJsonDtoMapper.Map(object);
return JsonConvert.SerializeObject(dtoMappedObject);

If you want to expand this there are libraries like AutoMapper that can help. This provides a framework for building these Mapper classes.

tigerswithguitars
  • 2,359
  • 1
  • 34
  • 52