.NET 7 Preview 5
is out and we now have improved Polymorphic Serialization/Deserialization
Support in
System.Text.Json.
Consider the following classes.
public class Person { public string Name { get; set; } } public class Student : Person { public int StudentId { get; set; } } public class Employee : Person { public int EmployeeId { get; set; } }
Now if I do something like the below, you can see it only serialized the
properties that are in the Parent class. (wrote a post about this a
couple of months back: System.Text.Json.JsonSerializer: Serialize Properties of Derived Classes).
JsonSerializerOptions options = new() { WriteIndented = true }; Person person = new Student { Name = "John Doe", StudentId = 1 }; string jsonString = JsonSerializer.Serialize<Person>(person, options); Console.WriteLine(jsonString); //{ // "Name": "John Doe" //}
We can change this behavior now using JsonDerivedType attribute
annotations.
[JsonDerivedType(typeof(Student))] [JsonDerivedType(typeof(Employee))] public class Person { public string Name { get; set; } }
This configuration enables polymorphic serialization for Person,
specifically when the runtime type is one of the derived classes.
Now if we do something like the below, we can see correct runtime types are
getting serialized.
JsonSerializerOptions options = new() { WriteIndented = true }; Person person = new Student { Name = "John Doe", StudentId = 1 }; string jsonString = JsonSerializer.Serialize<Person>(person, options); Console.WriteLine(jsonString); //{ // "StudentId": 1, // "Name": "John Doe" //} person = new Employee { Name = "Jane Doe", EmployeeId = 1 }; jsonString = JsonSerializer.Serialize<Person>(person, options); Console.WriteLine(jsonString); //{ // "EmployeeId": 1, // "Name": "Jane Doe" //}
If I try to serialize a derived type that's not annotated in the base class, I
am going to see an exception like the one below.
System.NotSupportedException: Runtime type 'Teacher' is not supported by polymorphic type 'Person'
Now when deserializing, it would be as follows.
string jsonString = """ { "StudentId": 1, "Name": "John Doe" } """; Person person = JsonSerializer.Deserialize<Person>(jsonString); Console.WriteLine(person is Student); // false, polymorphic deserialization doesn't work
Here note that this does not enable polymorphic
deserialization.
In order to enable polymorphic deserialization, we need to specify a type
discriminator.
[JsonDerivedType(typeof(Student), typeDiscriminator: "student")] public class Person { public string Name { get; set; } }
Now when we serialize, the JSON will include the type discriminator.
Person person = new Student { Name = "John Doe", StudentId = 1 }; string jsonString = JsonSerializer.Serialize<Person>(person, options); Console.WriteLine(jsonString); //{ // "$type": "student", // "StudentId": 1, // "Name": "John Doe" //}
Now when deserializing, we can see polymorphic deserialization works.
string jsonString = """ { "$type": "student", "StudentId": 1, "Name": "John Doe" } """; Person person = JsonSerializer.Deserialize<Person>(jsonString); Console.WriteLine(person is Student); // true, polymorphic deserialization works
Hope this helps.
Happy Coding.
Regards,
Jaliya
No comments:
Post a Comment