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与对象转换的方法,不过那样我感觉不太好。针对继承类型的集合序列化,反序列化,子类字段不缺失,值也不缺失。
分类:
C#
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库