Why does System.Text Json Serialiser not serialise this generic property but Json.NET does?

后端 未结 1 1507
盖世英雄少女心
盖世英雄少女心 2021-01-19 21:39

I have the following situation. I have simplified the problem into the following example, although my real situation is more complicated.

System.Text.Json

1条回答
  •  悲&欢浪女
    2021-01-19 22:31

    This is a documented limitation of System.Text.Json. From the docs:

    Serialize properties of derived classes

    Serialization of a polymorphic type hierarchy is not supported. For example, if a property is defined as an interface or an abstract class, only the properties defined on the interface or abstract class are serialized, even if the runtime type has additional properties. The exceptions to this behavior are explained in this section....

    To serialize the properties of the derived type in the preceding example, use one of the following approaches:

    1. Call an overload of Serialize that lets you specify the type at runtime...

    2. Declare the object to be serialized as object.

    In your case A.TObject is declared to be of type B but is actually of type B in the instance you construct, so only the properties of the base class B are getting serialized as per the documentation. So that's that. For further discussion see the closed issue System.Text.Json.JsonSerializer doesn't serialize properties from derived classes #31742.

    There are several workarounds available, however. Firstly, you could construct obj as its most possibly derived type A>:

    var obj = new A> { TObject = new B() };
    

    Now all properties of TObject get serialized. Demo fiddle #1 here. But unfortunately you can't use this workaround since The actual TObject of B is not known until runtime.

    Alternatively, if you only need to serialize your obj, you could follow suggestion #2 from the docs and declare an object-typed surrogate property, and serialize that:

    public class A : A where T : class, new()
    {
        [System.Text.Json.Serialization.JsonPropertyName("TObject")]
        [Newtonsoft.Json.JsonIgnore]
        public object SerializedTObject => TObject;
    
        [System.Text.Json.Serialization.JsonIgnore]
        public T TObject { get; set; } = new T();
    }
    

    Note that JsonSerializerOptions.IgnoreReadOnlyProperties must not be set for read-only properties to be serialized.

    Demo fiddle #2 here.

    Finally, if you need polymorphic serialization and deserialization, you will need to write a custom JsonConverter. To get started see

    • Is polymorphic deserialization possible in System.Text.Json?
    • Serialize/Deserialize a class hierarchy with .NET Core System.Text.Json
    • System.Text.Json and Dynamically Parsing polymorphic objects.

    0 讨论(0)
提交回复
热议问题