简体   繁体   中英

How to Serialize abstract class in System.Text.Json

I have the following 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();
        }
    }

I know that polymorphic is not supported in .NET Core but I found several answers here

Is polymorphic deserialization possible in System.Text.Json?

The problem is that all the answers are for situations where we have a model class But in my example, the model class is not specified and is created by the user.

I also tried this answer and it worked without any problems But I do not want to use an external library in my project

use this

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();
    }
}

and when you want serialize:

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

Maybe just split Data and class, you can avoid this issue.

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM