Reputation: 36050
JSON.NET (by Newtonsoft) has great support for serializing and deserializing complex objects.
I am curious about using System.Text.Json
instead of JSON.NET and I am not able to find a good tutorial on the internet.
The .NET 7 preview has support for deserializing polymorphic objects. Here is an example using .NET 7 preview and C# 11:
// _To run it you will need net7 preview and c# 11_
using System.Text.Json.Serialization;
var testPolymorphism = new TestPolymorphysm()
{
Animals = new List<Animal>()
{
new Fish() {
Id = "fish1",
Name = "GoldFish",
Action = new ActionSwim() { DistanceSwam = 10 }
},
new Dog() {
Id = "dog1",
Name = "Tom",
Action = new ActionRun() { DistanceRan = 50 }
}
}
};
// serialize
var jsonSerialized = System.Text.Json.JsonSerializer.Serialize(testPolymorphism);
Console.WriteLine(jsonSerialized);
// deserialize
var clonePolymorphysm = System.Text.Json.JsonSerializer.Deserialize<TestPolymorphysm>(jsonSerialized);
Console.WriteLine(clonePolymorphysm);
// === MODELS ===
class TestPolymorphysm
{
public List<Animal> Animals { get; set; } = new();
}
[JsonDerivedType(derivedType: typeof(Dog), typeDiscriminator: "foo1")]
[JsonDerivedType(derivedType: typeof(Fish), typeDiscriminator: "foo2")]
abstract class Animal
{
public required string Id { get; set; }
public required string Name { get; set; }
}
class Dog : Animal
{
public required IAction Action { get; set; }
public AnimalType ExtensionType => AnimalType.Dog;
}
class Fish : Animal
{
public required IAction Action { get; set; }
public AnimalType ExtensionType => AnimalType.Fish;
}
[JsonDerivedType(derivedType: typeof(ActionSwim), typeDiscriminator: "foo3")]
[JsonDerivedType(derivedType: typeof(ActionRun), typeDiscriminator: "foo4")]
interface IAction { }
class ActionSwim : IAction
{
public required int DistanceSwam { get; set; }
}
class ActionRun : IAction
{
public required int DistanceRan { get; set; }
}
public enum AnimalType
{
Fish,
Dog
}
Anyways this code works thanks to JsonDerivedType
attributes but I am not sure why it works. Why is it that if I remove the typeDiscriminators foo1, foo2, foo3 and foo4 it does not work? I want to make sure I understand how it works before I use it.
Upvotes: 5
Views: 10162
Reputation: 339
The process is described in the documentation: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0#polymorphic-type-discriminators
To enable polymorphic deserialization, you must specify a type discriminator for the derived class ... With the added metadata, specifically, the type discriminator, the serializer can serialize and deserialize the payload ... Serialization will emit JSON along with the type discriminator metadata
Essentially, the JsonDerivedTypeAttribute
identifies supported derived types and adds the type discriminator $type
as JSON metadata, which in turn instructs the serializer.
Upvotes: 3
Reputation: 36050
Sorry I was not paying attention to the serialized object. It contains: "$type": "foo1",
, "$type": "foo2",
etc..
That's why the deserializer knows how to deserialize the object.
Upvotes: 2