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与对象转换的方法,不过那样我感觉不太好。针对继承类型的集合序列化,反序列化,子类字段不缺失,值也不缺失。

浙公网安备 33010602011771号