KtorでKotlinのRESTful APIを作成する方法
コード例: tutorial-server-restful-api
使用プラグイン:
このチュートリアルでは、KotlinとKtorを使用してバックエンドサービスを構築する方法を説明します。JSONファイルを生成するRESTful APIの例も紹介します。
次のことを学習します。
- JSONシリアライズを使用するRESTfulサービスを作成する。
- コンテンツネゴシエーションのプロセスを理解する。ContentNegotiationプラグインは、クライアントとサーバー間のメディアタイプをネゴシエートすることと、コンテンツを特定の形式でシリアライズ/デシリアライズすることという、2つの主要な目的を果たします。
- Ktor内でREST APIのルートを定義する。
前提条件
このチュートリアルは単独で行うこともできますが、
IntelliJ IDEAをインストールすることをお勧めしますが、任意のIDEを使用することもできます。
Hello RESTfulタスクマネージャー
このチュートリアルでは、既存のタスクマネージャーをRESTfulサービスとして書き換えます。これを行うには、いくつかのKtor
既存のプロジェクトに手動で追加することもできますが、新しいプロジェクトを生成し、以前のチュートリアルのコードを段階的に追加する方が簡単です。すべてのコードを繰り返していくので、以前のプロジェクトを手元に置く必要はありません。
Ktorプロジェクトジェネレーターに移動します。
Project artifact フィールドに、プロジェクトアーティファクトの名前としてcom.example.ktor-rest-task-appを入力します。
プラグインセクションで、Addボタンをクリックして次のプラグインを検索し、追加します。
- Routing
- Content Negotiation
- Kotlinx.serialization
- Static Content
プラグインを追加すると、プロジェクト設定の下に4つのプラグインすべてがリストされます。
Downloadボタンをクリックして、Ktorプロジェクトを生成しダウンロードします。
以前にIntelliJ IDEAでKtorプロジェクトを開き、探索し、実行するチュートリアルで説明したように、IntelliJ IDEAでプロジェクトを開きます。
src/main/kotlin/com/exampleに移動し、modelというサブパッケージを作成します。
modelパッケージ内に、新しいTask.ktファイルを作成します。
Task.ktファイルを開き、優先順位を表す
enum
とタスクを表すclass
を追加します。kotlin以前のチュートリアルでは、拡張関数を使用して
Task
をHTMLに変換しました。この場合、Task
クラスはkotlinx.serialization
ライブラリのSerializable
型でアノテーションが付けられています。Routing.ktファイルを開き、既存のコードを以下の実装に置き換えます。
kotlin以前のチュートリアルと同様に、URL
/tasks
へのGETリクエストのルートを作成しました。 今回は、手動でタスクリストを変換するのではなく、単にリストを返しています。IntelliJ IDEAで、実行ボタン (
) をクリックしてアプリケーションを開始します。
ブラウザでhttp://0.0.0.0:8080/tasksに移動します。以下に示すように、タスクリストのJSONバージョンが表示されるはずです。

明らかに、私たちの代わりに多くの作業が実行されています。一体何が起こっているのでしょうか?
コンテンツネゴシエーションを理解する
ブラウザ経由のコンテンツネゴシエーション
プロジェクトを作成したとき、
HTTPでは、クライアントはAccept
ヘッダーを介してレンダリングできるコンテンツタイプを通知します。このヘッダーの値は1つ以上のコンテンツタイプです。上記の場合、ブラウザに組み込まれている開発ツールを使用して、このヘッダーの値を調べることができます。
次の例を検討してください。
/
の組み込みに注意してください。このヘッダーは、HTML、XML、または画像を_受け入れる_ことを示していますが、 他のコンテンツタイプも_受け入れます_。
Content Negotiationプラグインは、ブラウザにデータを送り返す形式を見つける必要があります。プロジェクトの生成されたコードを調べると、src/main/kotlin/com/example内にSerialization.ktというファイルがあり、次の内容が含まれています。
このコードはContentNegotiation
プラグインをインストールし、kotlinx.serialization
プラグインも構成します。これにより、クライアントがリクエストを送信すると、サーバーはJSONとしてシリアライズされたオブジェクトを返送できます。
ブラウザからのリクエストの場合、ContentNegotiation
プラグインはJSONのみを返すことができることを認識しており、ブラウザは送信されたものを表示しようとします。したがって、リクエストは成功します。
これをシミュレートするには、src/main/resources/static内のindex.htmlページを開き、デフォルトのコンテンツを次のもので置き換えます。
htmlこのページにはHTMLフォームと空のテーブルが含まれています。フォームを送信すると、JavaScriptイベントハンドラーが
Accept
ヘッダーをapplication/json
に設定して/tasks
エンドポイントにリクエストを送信します。返されたデータはデシリアライズされ、HTMLテーブルに追加されます。IntelliJ IDEAで、再実行ボタン (
) をクリックしてアプリケーションを再起動します。
URL http://0.0.0.0:8080/static/index.htmlに移動します。 View The Tasksボタンをクリックしてデータを取得できるはずです。
本番環境では、JSONをブラウザに直接表示したくありません。代わりに、ブラウザ内でJavaScriptコードが実行され、リクエストを行い、返されたデータをシングルページアプリケーション(SPA)の一部として表示します。通常、この種のアプリケーションはReact、 Angular、 またはVue.jsのようなフレームワークを使用して記述されます。
GETルートを追加する
コンテンツネゴシエーションのプロセスに慣れたところで、
タスクリポジトリを再利用する
タスクのリポジトリは修正なしで再利用できるので、まずそれを行います。
modelパッケージ内に新しいTaskRepository.ktファイルを作成します。
TaskRepository.ktを開き、以下のコードを追加します。
kotlin
GETリクエストのルートを再利用する
リポジトリを作成したので、GETリクエストのルートを実装できます。タスクをHTMLに変換する心配をする必要がないため、以前のコードを簡略化できます。
src/main/kotlin/com/example内のRouting.ktファイルに移動します。
Application.configureRouting()
関数内の/tasks
ルートのコードを以下の実装で更新します。kotlinこれにより、サーバーは次のGETリクエストに応答できます。
/tasks
: リポジトリ内のすべてのタスクを返します。/tasks/byName/{taskName}
: 指定されたtaskName
でフィルタリングされたタスクを返します。/tasks/byPriority/{priority}
: 指定されたpriority
でフィルタリングされたタスクを返します。
IntelliJ IDEAで、再実行ボタン (
) をクリックしてアプリケーションを再起動します。
機能をテストする
これらのルートはブラウザでテストできます。たとえば、http://0.0.0.0:8080/tasks/byPriority/Mediumに移動すると、Medium
優先順位のすべてのタスクがJSON形式で表示されます。

これらの種類のリクエストは通常JavaScriptから来ることを考えると、よりきめ細かなテストが望ましいです。これには、Postmanなどの専用ツールを使用できます。
Postmanで、URL
http://0.0.0.0:8080/tasks/byPriority/Medium
で新しいGETリクエストを作成します。Headersペインで、Acceptヘッダーの値を
application/json
に設定します。Sendをクリックしてリクエストを送信し、レスポンスビューアーでレスポンスを確認します。
プロジェクトのルートディレクトリに、新しいREST Task Manager.httpファイルを作成します。
REST Task Manager.httpファイルを開き、次のGETリクエストを追加します。
httpIntelliJ IDE内でリクエストを送信するには、その横にあるガターアイコン (
) をクリックします。
これはServicesツールウィンドウで開かれ、実行されます。
IntelliJ IDEA Ultimateでは、HTTPリクエストファイルで同じ手順を実行できます。
NOTE
ルートをテストする別の方法として、Kotlin Notebook内からkhttpライブラリを使用することもできます。POSTリクエストのルートを追加する
以前のチュートリアルでは、HTMLフォームを介してタスクが作成されました。しかし、今回はRESTfulサービスを構築しているため、その必要はありません。代わりに、kotlinx.serialization
フレームワークを使用し、ほとんどの重い処理を任せます。
src/main/kotlin/com/example内のRouting.ktファイルを開きます。
Application.configureRouting()
関数に新しいPOSTルートを次のように追加します。kotlin次の新しいインポートを追加します。
kotlinPOSTリクエストが
/tasks
に送信されると、kotlinx.serialization
フレームワークがリクエストのボディをTask
オブジェクトに変換するために使用されます。これが成功すると、タスクがリポジトリに追加されます。デシリアライズプロセスが失敗した場合は、サーバーはSerializationException
を処理する必要があり、タスクが重複している場合はIllegalStateException
を処理する必要があります。アプリケーションを再起動します。
この機能をPostmanでテストするには、URL
http://0.0.0.0:8080/tasks
に新しいPOSTリクエストを作成します。Bodyペインに、新しいタスクを表す次のJSONドキュメントを追加します。
jsonSendをクリックしてリクエストを送信します。
http://0.0.0.0:8080/tasksにGETリクエストを送信することで、タスクが追加されたことを確認できます。
IntelliJ IDEA Ultimateでは、HTTPリクエストファイルに次を追加することで同じ手順を実行できます。
http
削除のサポートを追加する
サービスの基本的な操作の追加はほぼ完了しました。これらはしばしばCRUD操作(作成、読み取り、更新、削除の略)として要約されます。次に、削除操作を実装します。
TaskRepository.ktファイルで、
TaskRepository
オブジェクト内に、名前でタスクを削除する次のメソッドを追加します。kotlinRouting.ktファイルを開き、DELETEリクエストを処理するためのエンドポイントを
routing()
関数に追加します。kotlinアプリケーションを再起動します。
HTTPリクエストファイルに次のDELETEリクエストを追加します。
httpIntelliJ IDE内でDELETEリクエストを送信するには、その横にあるガターアイコン (
) をクリックします。
Servicesツールウィンドウにレスポンスが表示されます。
Ktorクライアントでユニットテストを作成する
これまではアプリケーションを手動でテストしていましたが、既にお気づきのとおり、このアプローチは時間がかかり、スケーラブルではありません。代わりに、組み込みの client
オブジェクトを使用してJSONを取得し、デシリアライズする
src/test/kotlin/com/example内のApplicationTest.ktファイルを開きます。
ApplicationTest.ktファイルの内容を次のもので置き換えます。
kotlinサーバーで行ったのと同様に、プラグインに
ContentNegotiation
プラグインとkotlinx.serialization
プラグインをインストールする必要があることに注意してください。gradle/libs.versions.tomlにあるバージョンカタログに次の依存関係を追加します。
yamlbuild.gradle.ktsファイルに新しい依存関係を追加します。
kotlin
JsonPathでユニットテストを作成する
Ktorクライアントや類似のライブラリでサービスをテストするのは便利ですが、品質保証(QA)の観点から見ると欠点があります。サーバーはJSONを直接処理しないため、JSON構造に関する前提が正しいかどうかを確実に判断できません。
たとえば、次のような前提です。
- 値が実際には
object
が使用されているにもかかわらず、array
に格納されている。 - プロパティが実際には
strings
であるにもかかわらず、numbers
として格納されている。 - メンバーが宣言順にシリアライズされていないのに、そのようにされている。
サービスが複数のクライアントで使用されることを意図している場合、JSON構造に信頼性を持たせることは非常に重要です。これを実現するには、Ktorクライアントを使用してサーバーからテキストを取得し、JSONPath ライブラリを使用してこのコンテンツを分析します。
build.gradle.ktsファイルで、
dependencies
ブロックにJSONPathライブラリを追加します。kotlinsrc/test/kotlin/com/exampleフォルダに移動し、新しいApplicationJsonPathTest.ktファイルを作成します。
ApplicationJsonPathTest.ktファイルを開き、以下のコンテンツを追加します。
kotlinJsonPathクエリは次のように機能します。
$[*].name
: 「ドキュメントを配列として扱い、各エントリの名前プロパティの値を返す」という意味です。$[?(@.priority == '$priority')].name
: 「配列内の、指定された値と等しい優先順位を持つすべてのエントリの名前プロパティの値を返す」という意味です。
これらのクエリを使用して、返されたJSONの理解を確認できます。コードのリファクタリングやサービスの再デプロイを行う際、シリアライズの変更は、現在のフレームワークでのデシリアライズを中断しない場合でも特定されます。これにより、自信を持って公開APIを再公開できます。
次のステップ
おめでとうございます!タスクマネージャーアプリケーションのRESTful APIサービスの作成を完了し、KtorクライアントとJsonPathを使用したユニットテストの細部を学習しました。
次の