How can I “un-JsonIgnore” an attribute in a derived class?

I am using Newtonsoft JsonSerializer to serialize some classes.

As I wanted to skip one field of my class during serialization, I declared the following:

[JsonIgnore] public int ParentId { get; set; } 

This worked, but now I am faced with a new problem: in a derived class, I would like this field to appear (and do it only in this particular derived class).

I also looked at the documentation on the Internet to override this option in child classes (I think I need something like [JsonStopIgnore] , but I could not find anything close).


  • Is there a way to get me JsonSerializer to pick up this attribute again?
  • Is it possible to explicitly specify an attribute as [JsonIgnore] , but only in the base class?
+8
json c # jsonserializer
source share
5 answers

You can do this by creating a custom DefaultContractResolver and overriding its CreateProperty method.

For example, given the base Foo and the derivative Bar :

 public class Foo { [JsonIgnore] public string Name { get; set; } public int Age { get; set; } } public class Bar : Foo { } 

You can create the following contract resolver:

 public class MyTypeContractResolver<T> : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); property.Ignored = false; property.ShouldSerialize = propInstance => property.DeclaringType != typeof (T); return property; } } 

This sets all the properties of Ignored = false , and then analyzes them according to the given predicate:

 propInstance => property.DeclaringType != typeof (T); 

Which in our case means "you should serialize only if they are not of type Foo " (because Foo is DeclaryingType ).

And then, when you want to deserialize, you pass the contract recognizer instance to JsonSerializerSettings :

 var bar = new Bar(); var result = JsonConvert.SerializeObject(bar, new JsonSerializerSettings {ContractResolver = new MyTypeContractResolver<Bar>()}); 
+7
source share

The only way to "override" the behavior of the [JsonIgnore] attribute is to use a contract resolver, as @ Yuval Itchakov perfectly explained in his answer.

However, there is another possible solution that may work for you: instead of using the [JsonIgnore] attribute, you can implement the ShouldSerializeParentId() method in your classes to determine if the ParentId property will be serialized. In the base class, make this method return false ; then override the method in the derived class to return true . (This function is called serialization of conditional properties in Json.Net.)

 public class Base { public int Id { get; set; } public int ParentId { get; set; } public virtual bool ShouldSerializeParentId() { return false; } } public class Derived : Base { public override bool ShouldSerializeParentId() { return true; } } 

Fiddle: https://dotnetfiddle.net/65sCSz

+9
source share

You can probably just rewrite the ParentId in the derived class.

 public new int ParentId { get { return base.ParentId; } set { base.ParentId = value; } } 
+3
source share

I solved the same problem using a new keyword in a property of a derived class.

 public class Foo { [JsonIgnore] public int ParentId { get; set; } } public class Bar: Foo { [JsonProperty("ParentId")] public new int ParentId { get; set; } } 
+2
source share

I solved the same problem with a ghost property:

 public class Foo { [JsonIgnore] public int ParentId { get; set; } [NotMapped] public int FooParent { get; set; } } 

When I want to show this property, which is always hidden, I fill it, other values ​​are null:

 Foos.ForEach(x => x.FooParent = ParentId); 
+1
source share

All Articles