Newtonsoft.json: JsonIgnore attribute on shadowed properties

Created on 15 Jan 2015  路  6Comments  路  Source: JamesNK/Newtonsoft.Json

JsonIgnore atrribute does not work properly in case of shadowed class properties. Sample code:

using Newtonsoft.Json;

namespace jsonnet_cs_test
{
    class Base
    {
        public string prop1 { get; set; }
    }

    class Derived: Base
    {
        [JsonIgnore]
        public new string prop1 { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine(JsonConvert.SerializeObject(new Derived { prop1 = "x" }));
            //output: {"prop1":null}

            System.Console.ReadKey();
        }
    }
}

Most helpful comment

@JamesNK

If you want to ignore both then place [JsonIgnore] on both, or if you want [JsonIgnore] on the Derived class to ignore both then base the property virtual and override it on Derived.

What about the times you want to ignore both, but you don't own Base and have no access to its code?

All 6 comments

I thought about this yesterday and I don't believe this is a bug. I think the old Json.NET 4.5 behavior was the bug that has since been fixed.

They are separate properties, one happens to be hiding the other. By ignoring the one on Derived then the property on base is no longer hidden and is being serialized instead. If you want to ignore both then place [JsonIgnore] on both, or if you want [JsonIgnore] on the Derived class to ignore both then base the property virtual and override it on Derived.

Make sense?

It makes sense. In a way. In the technology point of view shadowed properties are indeed different properties, as well as overridden properties are by the same logic. So what you says makes sense. But the question is what is a shadowed property actually, what your purpose with using that and what your "intuitive expectation" when you use it. I don't know what was the intentions of the creators originally, but the only thing what I can figure is hiding and forgetting the original property without having the functionality of VMT, which is exactly my purpose with them. I don't want to redefine a behavior of something and be type aware as in case of a virtual property or function, I just wanted to decorate with other attributes, and forget the original property. You say hiding (jsonignore) the property makes the base property visible. I think this logic is not correct. JsonIgnore does not change the fact that the property is hidden/shadowed/overridden. It just change the behavior of the serializer, nothing else. So if what you say is right, than JsonIgnore should work the same way with overridden properties, and it does not (I tried). Does this explanation make sense?

By the way @paulduran should also follow this

Making [JsonIgnore] hide both is removing flexibility. If someone wants to serialize a hidden property then they have no one to configure that with attributes. Having [JsonIgnore] only hide the derived property lets them do that. I recall someone who had that scenario which is why I made the change.

@JamesNK

If you want to ignore both then place [JsonIgnore] on both, or if you want [JsonIgnore] on the Derived class to ignore both then base the property virtual and override it on Derived.

What about the times you want to ignore both, but you don't own Base and have no access to its code?

The problem is that the serialized data is ignored during deserialization, so, it's just kind of a waste of space right now. -- I don't have a preference one way or the other if the shadowed property is ignored or not, but ideally, the default deserialization behavior should follow the same nuances as the default serialization behavior. I've opened bug #1877 to discuss further.

Was this page helpful?
0 / 5 - 0 ratings