如何在 System.Text.Json 中序列化摘要 class
How to Serialize abstract class in System.Text.Json
我有以下class
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 不支持多态,但我在这里找到了几个答案
问题是所有答案都是针对我们有模型的情况 class 但在我的例子中,模型 class 没有指定,是由用户创建的。
我也尝试了 答案并且没有任何问题但是我不想在我的项目中使用外部库
也许只是拆分 Data 和 class ,你可以避免这个问题。
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();
}
}
使用这个
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);
我有以下class
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 不支持多态,但我在这里找到了几个答案
问题是所有答案都是针对我们有模型的情况 class 但在我的例子中,模型 class 没有指定,是由用户创建的。
我也尝试了
也许只是拆分 Data 和 class ,你可以避免这个问题。
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();
}
}
使用这个
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);