1

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

3
  • 1
    I do not want to use an external library in my project why not? If a library exists that solves a problem you're having, you should use that library instead of reinventing the wheel. Commented Apr 23, 2021 at 9:18
  • @IanKemp Because a dependency must be understood, maintained, and deployed. All of which adds to the burden of maintenance of the system over its lifetime. Every % add up. Commented Nov 6, 2023 at 12:16
  • I was having a somewhat similar problem where I needed to serialize/deserialize a list of abstract nodes containing concrete instances. I was able to do this with Polymorphic type discriminators - simply decorating my base class it adds metadata to the Json: learn.microsoft.com/en-us/dotnet/standard/serialization/… Commented Nov 7, 2024 at 14:23

2 Answers 2

6

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);
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.