Here are my codes:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Debug.WriteLine(JsonSerializer.Serialize<TestModel>(new TestModel() { Name = "123", Time = DateTime.Now }));
Debug.WriteLine(JsonSerializer.Serialize<TestModelWithGeneric<int>>(new TestModelWithGeneric<int>() { Name = "123", Time = DateTime.Now ,Value=1}));
Debug.WriteLine(JsonSerializer.Serialize<TestModelWithGeneric<string>>(new TestModelWithGeneric<string>() { Name = "123", Time = DateTime.Now, Value = "123" }));
}
[JsonDerivedType(typeof(TestModel), typeDiscriminator: "Base")]
[JsonDerivedType(typeof(TestModelWithGeneric<int>), typeDiscriminator: "TestModelWithInt")]
[JsonDerivedType(typeof(TestModelWithGeneric<string>), typeDiscriminator: "TestModelWithString")]
public class TestModel {
public string Name{ get; set; }
public DateTime Time { get; set; }
}
public class TestModelWithGeneric<T> :TestModel{
public T Value { get; set; }
}
}
The output is:
{"$type":"Base","Name":"123","Time":"2023-12-04T15:29:49.7867248+08:00"}
{"Value":1,"Name":"123","Time":"2023-12-04T15:29:49.8314012+08:00"}
{"Value":"123","Name":"123","Time":"2023-12-04T15:29:49.8354174+08:00"}
As you see, when there is a generic type, it always missing $type that JsonDerivedType no working.
What’s wrong with my code?
The framework I am working is .Net8 .
2
Answers
Problem solved! According to the How to serialize properties of derived classes with
System.Text.Json
doc:I should call
JsonSerializer.Serialize<T>
with explicitTestModel
provided for the generic argument:Then it works now!
TestModelWithGeneric<T>
does not have any polymorphic serialization info added so theSystem.Text.Json
serializer will not apply it when the serialized generic type is resolved asTestModelWithGeneric<T>
(generic types are resolved at compile time). You can specify type explicitly:But this is not ideal option because it is easy to miss calls (for example the call
JsonSerializer.Serialize(new TestModelWithGeneric<string>() ...)
will infer the "incorrect" type ofTestModelWithGeneric<string>
). Another option would be to use customIJsonTypeInfoResolver
. For example simple one can look like (handles onlyTestModel
but can be expanded for more generic handling):And usage:
Which results in:
See also: