如何在System.Text.Json中序列化抽象类



我有以下类

public abstract class Settings
{
private string _filename;

protected virtual void defaults()
{

}
public static T Load<T>(string filename) where T : Settings, new()
{
T theSetting;
if (File.Exists(filename))
{
var reader = new StreamReader(filename);
var configJson = reader.ReadToEnd();
reader.Close();
theSetting = System.Text.Json.JsonSerializer.Deserialize<T>(configJson);
}
else
{
theSetting = new T();
theSetting.defaults();
}
theSetting._filename = filename;
theSetting.Save();
return theSetting;
}
public void Save()
{
var writer = new StreamWriter(_filename);
writer.Write(JsonSerializer.Serialize(this));
writer.Close();
}
public void SaveAs(string filename)
{
_filename = filename;
Save();
}
}

我知道.NET Core不支持多态性,但我在这里找到了几个答案

在System.Text.Json中是否可以进行多态反序列化?

问题是,所有的答案都适用于我们有模型类的情况。但在我的示例中,模型类没有指定,而是由用户创建的。

我也尝试过这个答案,它没有任何问题,但我不想在我的项目中使用外部库

使用此

public class PolymorphicJsonConverter<T> : JsonConverter<T>
{
public override bool CanConvert(Type typeToConvert)
{
return typeof(T).IsAssignableFrom(typeToConvert);
}
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();
return;
}
writer.WriteStartObject();
foreach (var property in value.GetType().GetProperties())
{
if (!property.CanRead)
continue;
var propertyValue = property.GetValue(value);
writer.WritePropertyName(property.Name);
JsonSerializer.Serialize(writer, propertyValue, options);
}
writer.WriteEndObject();
}
}

当你想要序列化时:

options.Converters.Add(new PolymorphicJsonConverter<T>());
string json = JsonSerializer.Serialize(this, options);

也许只需拆分数据和类,就可以避免这个问题。

public abstract class Settings<T>
{
protected T _t;

protected virtual void defaults()
{

}
public static T Load<T>(string filename)
{
//....
} 
public void Save()
{
var writer = new StreamWriter(_filename);
writer.Write(JsonSerializer.Serialize(_t));
writer.Close();
}
}

最新更新