web-dev-qa-db-ja.com

REST API-APIはネストされたJSONオブジェクトを返す必要がありますか?

JSON APIに関しては、応答を平坦化し、ネストされたJSONオブジェクトを回避することは良い習慣ですか?

例として、IMDbに似ているがビデオゲーム用のAPIがあるとします。ゲーム、プラットフォーム、ESRBRating、およびゲームとプラットフォームをマップするGamePlatformMapの2つのエンティティがあります。

ID 1のゲームをフェッチする/ game/1をリクエストすると、プラットフォームとesrbRatingがネストされたゲームオブジェクトが返されます。

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"id":1,"name":"Xbox"},
    {"id":2,"name":"PlayStation"}
  ],
  "esrbRating": {
    "id": 1,
    "code": "E",
    "name": "Everyone"
  }
}

JPA/Hibernateのようなものを使用している場合、それがFETCH.EAGERに設定されていると、自動的にこれが実行されます。

もう1つのオプションは、単にAPIを使用してエンドポイントを追加することです。

その場合、/ game/1が要求されると、ゲームオブジェクトのみが返されます。

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
}

プラットフォームやESRBRatingが必要な場合は、以下を呼び出す必要があります。

/ game/1/platform/game/1/esrb

このメソッドは、クライアントが必要とするデータと必要なときに応じて、サーバーへの呼び出しをさらにいくつか追加する可能性があるようです。

このようなものが返ってくると私が思った最後の考えがありました。

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": ["Xbox","PlayStation"]
}

ただし、これは、IDまたはその他の情報がこれらのプラットフォームオブジェクトに関連付けられている必要がないことを前提としています。

一般に、APIから返されたJSONオブジェクトを構造化する最良の方法は何かを尋ねます。エンティティにできるだけ近づけるようにすべきですか、それともドメインオブジェクトまたはデータ転送オブジェクトを使用しても問題ありませんか?メソッドにはトレードオフがあることを理解しています。データアクセスレイヤーでの作業が増えるか、クライアントの作業が増えるかです。

また、JPA/Hibernateまたは永続化のためのMyBatisを使用して、APIのバックエンドテクノロジーとしてSpring MVCを使用することに関連する回答を聞きたいと思います。

41
greyfox

別の代替案(HATEOASを使用)。これは単純です。実際には、HATEOASの使用方法に応じて、ほとんどの場合jsonにリンクタグを追加します。

http://api.example.com/games/1

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"_self": "http://api.example.com/games/1/platforms/53", "name": "PlayStation"},
    {"_self": "http://api.example.com/games/1/platforms/34", "name": "Xbox"},
  ]
}

http://api.example.com/games/1/platforms/34

{
  "id": 34,
  "title": "Xbox",
  "publisher": "Microsoft",
  "releaseDate": "2015-01-01",
  "testReport": "http://api.example.com/games/1/platforms/34/reports/84848.pdf",
  "forms": [
    {"type": "edit", "fields: [] },
  ]
}

もちろん、すべてのデータをすべてのリストに埋め込むことができますが、データが多すぎる可能性があります。このようにして、必要なデータを埋め込んで、実際に操作したい場合は、さらに読み込むことができます。

技術的な実装にはキャッシングを含めることができます。プラットフォームのリンクと名前をゲームオブジェクトにキャッシュして、プラットフォームのAPIをまったくロードしなくてもすぐに送信できます。その後、必要に応じてロードできます。

たとえば、フォーム情報をいくつか追加したことがわかります。詳細なjsonオブジェクトには、ゲームのリストにロードしたい情報よりもはるかに多くの情報がある可能性があることを示すためにそれを行いました。

11
Luc Franken

これは、REST API設計に関しては、これらの基本的な質問の1つです。すべての設計者は、初日にこの質問をします。申し訳ありませんが、答えは「場合によります」です。それぞれのアプローチには長所と短所があります。短所とあなたはただ決定を下し、それで行く必要があるでしょう。

16
RibaldEddie

ここで紹介するアプローチの2番目 https://www.slideshare.net/stormpath/rest-jsonapis

つまり、ネストされたリソースをリンクとして親リソースに含め、一方、親エンドポイントで展開パラメーターを提供します。

私の意見では、これはほとんどの場合効率的で柔軟な方法です。

5
Wei Qiu