Skip to main content
edited body
Source Link
dbc
  • 119.7k
  • 27
  • 273
  • 404
  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modifiedmodifier to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    

    For more see Knowing When to Use Override and New Keywords (C# Programming Guide).

  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modified to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    

    For more see Knowing When to Use Override and New Keywords (C# Programming Guide).

  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modifier to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    

    For more see Knowing When to Use Override and New Keywords (C# Programming Guide).

added 223 characters in body
Source Link
dbc
  • 119.7k
  • 27
  • 273
  • 404
  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modified to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    

    For more see Knowing When to Use Override and New Keywords (C# Programming Guide).

  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modified to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    
  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modified to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    

    For more see Knowing When to Use Override and New Keywords (C# Programming Guide).

Source Link
dbc
  • 119.7k
  • 27
  • 273
  • 404

Json.NET will never serialize two properties with the same name. If DefaultContractResolver encounters two identically named properties, it chooses to serialize the most derived property that is not ignored. Notably, this decision is based on static metadata such as the presence of absence of [JsonIgnore] -- and not on runtime state such as the return from ShouldSerialize.

Thus, to make A.Id supersede B.Id when serializing an instance of B, you must override CreateProperty() as follows:

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
    var property = base.CreateProperty(member, memberSerialization);
    if (member.ReflectedType == typeof(B)) // Use (typeof(A).IsAssignableFrom(member.ReflectedType)) if you want this to apply to all subclasses of A
    {
        // Make A.Id supersede B.Id
        if (member.Name == nameof(A.Id) && member.DeclaringType != typeof(A))
            property.Ignored = true;
    }
    return property;
}

In addition, if you want really ony want the Id property of class A to be visible when serializing an instance of B, you must in addition remove or ignore everything else in CreateProperties():

protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
    var properties = base.CreateProperties(type, memberSerialization);
    if (type == typeof(B)) // Use typeof(A).IsAssignableFrom(type)) if you want to only serialize the Id property of A and all its subclasses
    {
        // Remove everything except Id.  You could also Ignore everything except Id.
        properties = properties.Where(p => p.UnderlyingName == nameof(A.Id)).ToList();
    }
    return properties;
}

Notes:

  • Presumably Newtonsoft does not check ShouldSerialize to determine which Id property to bind to JSON because ShouldSerialize cannot be called during deserialization.

  • If you really just want to serialize { "id": "A:ID" } for every instance of A or any subclass of A, use typeof(A).IsAssignableFrom() where I mention it in code comments.

  • You should mark B.Id with the new modified to avoid a compilation warning.

    public class B : A
    {
        [JsonProperty("id")]
        public new string Id { get { return "B:ID"; } } // Fixed compilation
    

Demo fiddle here;