前言
假設有一個 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 抽象基類,System.Text.Json
內置功能已經可以直接支持序列化派生類:
[HttpGet]
[Route("get")]
public?Person?Get()
{Person?person?=?new?Student?{?Name?=?"zhangsan",?Score?=?100?};return?person;
}
但是,當 API 需要返回 Person 抽象基類的集合時,System.Text.Json
就不知道如何處理了,即使集合內部只有一種派生類型:
[HttpGet]
[Route("list")]
public?IEnumerable<Person>?List()
{return?new?Person[]?{new?Student?{?Name?=?"zhangsan",?Score?=?100?}};
}
可以看到,只處理了基類的屬性。
我們必須主動告訴System.Text.Json
如何處理序列化派生類,因此需要自定義轉換器。
解決方案
為基類創建自定義轉換器:
public?class?PersonConverter?:?JsonConverter<Person>
{public?override?Person?Read(ref?Utf8JsonReader?reader,?Type?typeToConvert,?JsonSerializerOptions?options){throw?new?NotImplementedException();}public?override?void?Write(Utf8JsonWriter?writer,?Person?person,?JsonSerializerOptions?options){writer.WriteStartObject();if?(person?is?Student?student){writer.WriteNumber("score",?student.Score);}else?if?(person?is?Teacher?teacher){?writer.WriteString("title",?teacher.Title);}writer.WriteString("name",?person.Name);writer.WriteEndObject();}
}
然后修改 Startup.cs 文件,注冊自定義轉換器:
services.AddControllers().AddJsonOptions(options?=>options.JsonSerializerOptions.Converters.Add(new?PersonConverter()));
運行,序列化成功:
上面的轉換器代碼通過手動寫入每個屬性實現序列化,那屬性一多還不要累死!
一種替代方法是調用System.Text.Json
內置功能實現序列化單個派生類:
public?override?void?Write(Utf8JsonWriter?writer,?Person?person,?JsonSerializerOptions?options)
{JsonSerializer.Serialize(writer,?(object)person,?options);
}
注意,必須將要序列化的對象轉換為 object
結論
通過自定義轉換器,我們實現了使用System.Text.Json
序列化派生類。
添加微信號【MyIO666】,邀你加入技術交流群