Neu in .NET 7.0 [25]: Polymorphismus beim Deserialisieren mit System.Text.Json

Der JSON-Deserializer kann im jüngsten .NET-Framework ebenso polymorph arbeiten wie der JSON-Serializer.

In Pocket speichern vorlesen Druckansicht 5 Kommentare lesen

(Bild: Blackboard/Shutterstock.com)

Lesezeit: 1 Min.
Von
  • Dr. Holger Schwichtenberg

Im vorherigen Teil dieser Serie wurde Polymorphismus beim Serialisieren mit System.Text.Json (ab Version 7.0) vorgestellt. Der Typ-Diskriminator hilft auch beim Deserialisieren: Auch hierbei kann der JSON-Deserializer polymorph arbeiten.

Der Dotnet-Doktor – Holger Schwichtenberg

Dr. Holger Schwichtenberg ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher und mehr als 1500 Fachartikel gehört Holger Schwichtenberg zu den bekanntesten Experten für .NET und Webtechniken in Deutschland.

Wie im letzten Teil wird die Klasse Person mit ihrer Ableitung Consultant verwendet.

[JsonDerivedType(typeof(Person), typeDiscriminator: "P")]
[JsonDerivedType(typeof(Consultant), typeDiscriminator: "C")]
public class Person
{
 public required int ID { get; set; }
 public required string Name { get; set; }
 public override string ToString()
 {
  return $"Person {Name}";
 }
}
 
public class Consultant : Person
{
 public string? Company { get; set; }
 public override string ToString()
 {
  return $"Consultant {Name} arbeitet bei {Company}";
 }
}

Aus einer JSON-Zeichenkette ohne den Zusatz $type

var JSONohneTyp = """
                  {"ID":123,"Company":"www.IT-Visions.de",
                  "Name":"Holger Schwichtenberg"}
                  """;

entsteht nur dann ein Consultant-Objekt, wenn man explizit den Typ Consultant bei Deserialize<T>() angibt:

Consultant? p1a = 
  JsonSerializer.Deserialize<Consultant>(JSONohneTyp);
Console.WriteLine(p1a); // Consultant
 
Person? p1b = 
  JsonSerializer.Deserialize<Consultant>(JSONohneTyp);
Console.WriteLine(p1b); // Consultant

Person? p1c = 
  JsonSerializer.Deserialize<Person>(JSONohneTyp);
Console.WriteLine(p1c); // Person

Wenn es $type gibt

var JSONmitTyp = """"
                  {"$type":"C","ID":123,
                  "Company":"www.IT-Visions.de",
                  "Name":"Holger Schwichtenberg"}
                  """";

bekommt man in allen drei Fällen ein Consultant-Objekt, selbst wenn man Deserialize<Person>() aufruft!

Consultant? p2a = 
  JsonSerializer.Deserialize<Consultant>(JSONmitTyp);
Console.WriteLine(p2a); // Consultant
 
Person? p2b = 
  JsonSerializer.Deserialize<Consultant>(JSONmitTyp);
Console.WriteLine(p2b); // Consultant
 
Person? p2c = 
  JsonSerializer.Deserialize<Person>(JSONmitTyp);
// Wegen $type kriegen wir dennoch Consultant statt Person!
Console.WriteLine(p2c); 

System.Text.Json ist zusammen mit .NET 7.0 als NuGet-Paket erschienen, läuft aber auch unter .NET Standard 2.0 und damit auch auf .NET Core 2.x/3.x sowie .NET 5.0/.NET 6.0 auf dem klassischen .NET Framework ab Version 4.6.2.

(rme)