前言

上回,我们讲解了《如何序列化派生类》。

那如何反序列化派生类呢?

假设有一个 Person 抽象基类,其中包含 Student 和 Teacher 派生类:

public class Person{public string Name { get; set; }}public class Student : Person{public int Score { get; set; }}public class Teacher : Person{public string Title { get; set; }}

如果 API 输入类型是单个 Person 抽象基类,即使我们传入正确格式的派生类 JSON 字符串,System.Text.JSON也只会使用基类进行反序列化:

[HttpPost][Route("get")]public string Get(Person person){return person.GetType.ToString;}

类序列化的条件(如何反序列化派生类)(1)

我们必须主动告诉System.Text.Json如何处理反序列化派生类,因此需要自定义转换器。

思路

与序列化相反,我们需要实现自定义转换器的Read方法:

public class PersonConverter : JsonConverter<Person>{public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){}}

现在的关键是,如何判断到底要反序列化成哪个派生类型。

我们可以使用Read方法遍历 JSON 的所有 Property, 找到对应派生类型独有的属性,即可知道当前需要反序列化成哪个派生类型。

实现

为基类创建自定义转换器,实现Read方法:

public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){Utf8JsonReader readerClone = reader;while (readerClone.Read){JsonTokenType tokenType = readerClone.TokenType;switch (tokenType){case JsonTokenType.PropertyName:if (readerClone.ValueTextEquals("score")){return (Person)JsonSerializer.Deserialize(ref reader,typeof(Student), options);}else if (readerClone.ValueTextEquals("title")){return (Person)JsonSerializer.Deserialize(ref reader, typeof(Teacher), options);}break;}}throw new NotImplementedException;}

因为 Utf8JsonReader 是只进读取器,因此这里需要创建 Utf8JsonReader 实例的克隆readerClone去遍历 JSON,而原始 reader 用于反序列化派生类。

然后修改 Startup.cs 文件,注册自定义转换器:

services.AddControllers.AddJsonOptions(options =>options.JsonSerializerOptions.Converters.Add(new PersonConverter));

运行,反序列化成功:

类序列化的条件(如何反序列化派生类)(2)

结论

通过自定义转换器,我们实现了使用System.Text.Json反序列化派生类。

添加微信号【MyIO666】,邀你加入技术交流群

,