System.Text.Json serialization not using derived classes
Asked Answered
C

2

6

I have an abstract class named Extension which has several derived classes such as DerivedExtensionA, DerivedExtensionB, etc.

Now I have a list defined as List<Extension> which contains the derived classes instances.

Now if I serialize the above list, it only serializes the base class properties that are in Extension since the list has the base class Extension type. If I define the list as List<DerivedExtensionA> and then put only instances of DerivedExtensionA in it, then they are serialized fine. But my code is generic which is supposed to accept all types of Extensions, so this isn't a workable solution for me.

So question is ..

How do I keep the list defined as List<Extension> and still be able to fully serialize the contained derived class instances that contain ALL their properties ?

Here is a fiddle showing this behavior: https://dotnetfiddle.net/22mbwb

EDIT: Corrected the fiddle URL

Consternate answered 30/3, 2022 at 21:59 Comment(4)
I just corrected the fiddle URL.Consternate
This is as designed and documented. You can either 1) Add a JsonConverter<Extension> that serializes the derived classes explicitly as shown in Serialize objects implementing interface with System.Text.Json, or 2) serialize your List<Extension> via an IEnumerable<object> surrogate property as shown in System.Text.Json serialize derived class property.Abet
If you also need to deserialize you will need to add a type discriminator property. See Is polymorphic deserialization possible in System.Text.Json? for many converters that do this.Abet
Do those questions answer yours also, or do you need more specific help? Why does System.Text Json Serialiser not serialise this generic property but Json.NET does? also addresses this problem.Abet
D
4

From How to serialize properties of derived classes with System.Text.Json

Serialization of a polymorphic type hierarchy is not supported.

In your fiddle you can use an array of objects:

string allExtensionsSerialized =
   JsonSerializer.Serialize((object[])allExtensions.ToArray());

This is the hack I used recently:

public record MyType(
   // This nonsense is here because System.Text.Json does not support normal polymorphic serialisation
   [property: JsonIgnore] List<X> Messages))
{
   // This nonsense is here because System.Text.Json does not support normal polymorphic serialisation
   [JsonPropertyName("Messages")]
   public object[] MessagesTrick => Messages.ToArray();

For deserialisation, I decided used JsonDocument.Parse inside a dedicated FromJson(string json) method. This works OK, for me, in this specific case.

Distributary answered 31/3, 2022 at 0:23 Comment(0)
C
1

Actually I ended up changing the definition of the list from List<Extension> to List<object>, and the behavior was corrected. This might not be a workable solution for everyone reading this, but it's fine for me so that's why I'm adding my own answer.

Consternate answered 1/4, 2022 at 0:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.