Web APIインターフェースが実装クラスのコレクションを返す方法について

Web APIインターフェースが実装クラスのコレクションを返す方法について

Web APIインターフェースが基底クラスのリストを返す場合、テストインターフェースは基底クラスのプロパティのみを返します。実装クラスのプロパティはどのように返すのでしょうか?

最終更新 2023/03/19 20:55
沙漠尽头的狼
読了目安 2 分
カテゴリ
ASP.NET Core
タグ
.NET C# ASP.NET Core Web API

皆さんこんにちは、沙漠の果ての狼です。

一. 問題の説明

下図のように、StudentEmploy という2つのサブクラスを定義し、両方とも抽象クラス PersonBase を継承します:

public abstract class PersonBase
{
    public string Name { get; set; }

    protected PersonBase(string name)
    {
        Name = name;
    }
}

public class Student : PersonBase
{
    public string Number { get; set; }

    public Student(string name, string number) : base(name)
    {
        Number = number;
    }
}

public class Employ : PersonBase
{
    public string CompanyName { get; set; }

    public Employ(string name, string companyName) : base(name)
    {
        CompanyName = companyName;
    }
}

Web API インターフェースを追加し、基底クラスのコレクションを返します:

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    [HttpGet(Name = "GetDetails")]
    public IEnumerable<PersonBase> Get()
    {
        return new List<PersonBase>()
        {
            new Student("学生A", "学生号01"),
            new Employ("职员01", "百度")
        };
    }
}

インターフェースの戻り値:

[
  {
    "name": "学生A"
  },
  {
    "name": "职员01"
  }
]

問題に気づきましたか?Student クラスと Employ クラスのインスタンスの拡張プロパティ(StudentNumber プロパティ、EmployCompanyName プロパティ)がシリアライズされて表示されていません。では、どうすればサブクラスのすべてのプロパティをシリアライズできるのでしょうか?

二、クラスの全プロパティをシリアライズする方法

Microsoft のドキュメント「System.Text.Json を使用して派生クラスのプロパティをシリアライズする方法」を参考に、管理者が比較的簡単だと考える2つの実装方法を紹介します。

2.1、.NET 7 より前の実装方法

.NET 7 より前のバージョンでは、System.Text.Json はポリモーフィックな型階層のシリアライズをサポートしていません。例えば、インターフェースの戻り値の型がインターフェースや抽象クラスのコレクションである場合、実行時の型が他のプロパティを持っていても、インターフェースや抽象クラスで定義されたプロパティのみがシリアライズされます。

解決策: インターフェースの戻り値を IEnumerable<PersonBase> から object に変更し、インターフェース実装内の List<PersonBase>List<object> に変更します:

[HttpGet(Name = "GetDetails")]
public object Get()
{
    return new List<object>()
    {
        new Student("学生A", "学生号01"),
        new Employ("职员01", "百度")
    };
}

変更後、インターフェースは詳細な JSON 情報を正常に返します:

[
  {
    "number": "学生号01",
    "name": "学生A"
  },
  {
    "companyName": "百度",
    "name": "职员01"
  }
]

原理: object に変更すると、デフォルトで実装クラスがシリアライズされるようになります。変更前は System.Text.Json が実装クラスの親クラスしか認識していませんでした。

2.2、.NET 7 以降の実装方法

.NET 7 以降、System.Text.Json は属性を使用したポリモーフィックな型階層のシリアライズとデシリアライズをサポートしています。

インターフェースを元に戻し、抽象クラスに属性を追加して、基底クラスをシリアライズする際にマッピングするサブクラスの型を指定します:

[JsonDerivedType(typeof(Student))]
[JsonDerivedType(typeof(Employ))]
public abstract class PersonBase

問題は解決され、インターフェースの戻り値は上記と同じになります。

ドキュメントでは JsonDerivedTypeAttribute について次のように説明されています:型宣言に配置すると、ポリモーフィックシリアライゼーションのために指定されたサブタイプを選択する必要があることを示します。また、型識別子を指定する機能も公開します。

三、まとめ

上記2つの方法は、.NET のバージョンに応じて選択します。2つ目の方法では、サブクラスの型を明確に把握している必要があります。詳細な使用方法は Microsoft のドキュメント「System.Text.Json を使用して派生クラスのプロパティをシリアライズする方法」をご覧ください。

より良い方法があれば、ぜひコメントでご共有ください。

  • WeChat 技術交流グループ:WeChat(codewf)を追加し、「入群」とコメント
  • QQ 技術交流グループ:771992300
  • 画像リンクはそのまま掲載

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2022/06/22

ASP.NET Core WebAPI でローカリゼーションを実装する(単一リソースファイル)

Microsoft のデフォルトは、1 つのクラスに複数のリソースファイルを対応させる方法であり、使用がやや面倒です。本記事では、単一リソースファイルの使用方法を紹介します。つまり、プロジェクト全体のすべてのクラスが 1 セットの多言語リソースファイルに対応します。

続きを読む
同じカテゴリ / 同じタグ 2022/04/13

ASP.NET Core WebApiの戻り結果統一包装の実践

WebApiの結果を統一して返す際に、より良い制限方法や、よりシンプルで強力な結果のラッピングについて考えるようになりました。絶えず考えを巡らせ改善する中で、ようやく初歩的な成果を得たので共有します。学びに終わりはなく、考えにも終わりはありません。皆様と共に励みたいと思います。

続きを読む