Fork me on GitHub

system.text.Json 针对继承多态类型的集合,使用自定义Converter,进行json序列化

测试类:
[JsonConverter(typeof(PersonConverter))]
  public class Person
  {
      public string FirstName { get; set; }
      public string LastName { get; set; }
  }

  [JsonConverter(typeof(PersonConverter))]
  public class Employee : Person
  {
      public string Department { get; set; }
      public string JobTitle { get; set; }
  }
  [JsonConverter(typeof(PersonConverter))]
  public class Artist : Person
  {
      public string Skill { get; set; }
  }

  

自定义Converter:
public class PersonConverter : JsonConverter<Person>
{
    public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        JsonDocument.TryParseValue(ref reader, out var doc);
        var elm = doc.RootElement;
        elm.TryGetProperty("isBase", out var jEl);
        elm.TryGetProperty("typeName", out var typeEl);
        elm.TryGetProperty("obj", out var objEl);
      
        var typeStr = typeEl.GetString();
        var type = Type.GetType(typeStr);
        var objStr = objEl.GetRawText();
        var dic = JsonSerializer.Deserialize<Dictionary<string, string>>(objStr);

        var obj = ToObject(dic, type);
        return obj as Person;

    }

    public override bool CanConvert(Type typeToConvert)
    {
        if (typeToConvert == typeof(Person)) return true;
        if (typeToConvert.BaseType == typeof(Person)) return true;
        return false;
    }

    public override void Write(Utf8JsonWriter writer, Person value, JsonSerializerOptions options)
    {
        var type = value.GetType();

        var dic = new
        {
            typeName = type.FullName,
            obj = ToDictionary(value),

        };
        JsonSerializer.Serialize(writer, dic, options);
    }

    public Dictionary<string, object> ToDictionary(object obj)
    {
        if (obj == null)
            throw new ArgumentNullException(nameof(obj));

        var dictionary = new Dictionary<string, object>();
        foreach (var property in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (property.CanRead)
            {
                dictionary[property.Name] = property.GetValue(obj, null);
            }
        }
        return dictionary;
    }

    public T ToObject<T>(Dictionary<string, object> source) where T : class, new()
    {
        T result = new T();
        Type type = typeof(T);

        foreach (KeyValuePair<string, object> item in source)
        {
            PropertyInfo property = type.GetProperty(item.Key);
            if (property != null && property.CanWrite)
            {
                property.SetValue(result, item.Value, null);
            }
        }

        return result;
    }

    public object ToObject(IDictionary<string, string> source, Type type)
    {
        var result = Activator.CreateInstance(type);

        foreach (KeyValuePair<string, string> item in source)
        {
            PropertyInfo property = type.GetProperty(item.Key);
            if (property != null && property.CanWrite)
            {
                property.SetValue(result, item.Value, null);
            }
        }

        return result;
    }
}

  入口方法:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");
    List<Person> people = new List<Person>
        {
            new Employee(){Department="test part",
            FirstName="Hello",
            LastName="L",
            JobTitle="engineer"},
            new Person()
            {
            FirstName="ooook",
            LastName="is not",
            },
            new Artist()
            {
            FirstName="oooo",
            LastName="is not ooo",
            Skill="coding"
            },
        };
    var str = JsonSerializer.Serialize(people);
    Console.WriteLine(str);
    var pes = JsonSerializer.Deserialize<List<Person>>(str);
}

  

思路就是:转换成特定的类,然后需要借助Dictionary转换,不然直接使用serialize会出现循环调用,或者直接再引用一个newTonsoft.json取代dictionnary与对象转换的方法,不过那样我感觉不太好。针对继承类型的集合序列化,反序列化,子类字段不缺失,值也不缺失。
posted @ 2024-09-23 09:51  HelloLLLLL  阅读(22)  评论(0编辑  收藏  举报