Fork me on GitHub

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

测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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;
    }
}

  入口方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 @   HelloLLLLL  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示