オープンソースプロジェクト
skydoves/sandwich avatar
skydoves/sandwich

SandwichでKotlinのAPI結果を成功・エラー・例外に分けて扱う

プロジェクト概要:Sandwich は、Retrofit、Ktor、Kotlin Multiplatform 用の Kotlin で API 応答と例外を処理するために設計された、適応性のある軽量のシールされた API ライブラリです。

スター 1,773フォーク 114KotlinApache-2.0

ひと目でわかる

これは何?
skydoves/sandwichのREADMEをもとに、ApiResponseのsealedな結果型、コルーチン、再試行、グローバル処理、Retrofit・Ktor連携を整理します。
誰に向いている?
Sandwichは、ネットワークやI/Oの結果をSuccess、Failure.Error、Failure.Exceptionへ統一し、呼び出し側の分岐をKotlinらしいスコープと関数型オペレーターで組み立てたいチームに向きます。Retrofit、Ktor、Ktorfit、Kotlin Multiplatformをまたぐ共通処理や、再試行、トークン更新の置き場所を整理できます。
商用利用できる?
できます。Apache-2.0 は寛容なライセンスで、著作権表示とライセンス表示を残せば、使用・改変・販売が可能です。
今もメンテナンスされている?
されています。最後のコミットは 2 日前です。
何の言語で書かれている?
主に Kotlin です(GitHub の言語統計による)。

回答はプロジェクトの GitHub データ(最終同期:2026年9月18日)と当サイトの分析に基づくもので、法的助言ではありません。

オープンソース詳細解説

ラッパーを増やさずAPI結果をそろえる

skydoves/sandwichは、Retrofit、Ktor、Kotlin MultiplatformのAPI応答と例外を扱う軽量なsealed APIライブラリです。READMEの狙いは、ボディデータ、サーバーエラー、予期しない例外を標準化したインターフェースへ収め、レイヤーをまたぐ処理を短くすることです。アプリごとにResourceやResultのラッパークラスを作る代わりに、Sandwichが提供する結果型と関数型オペレーターを使います。

機能として、グローバルなレスポンス処理、Mapper、Operator、コルーチン向けのApiResponse拡張がREADMEに挙げられています。リポジトリのメタデータでは言語はKotlin、ライセンスはApache-2.0、既定ブランチはmain、アーカイブ状態はfalseです。2026年7月27日時点の取得情報には1,770スター、113フォーク、6件のオープンイシューが記録されています。ダウンロード数やスターは採用の参考であり、アプリのエラー設計が自動で正しくなる証拠ではありません。

ApiResponseの三つの分岐

中心となる`ApiResponse`は、ネットワーク、データベースなどのAPIまたはI/O呼び出しから一貫した結果を作るインターフェースとして説明されています。`ApiResponse.Success`は成功したデータを保持し、必要ならデータの出所を区別する`tag`も持てます。`ApiResponse.Failure.Error`は不正なリクエストやサーバー内部エラーのような失敗で、詳細なエラーペイロードを保持します。`ApiResponse.Failure.Exception`は、接続失敗など、リクエスト作成や応答処理で捕捉した予期しない例外を表します。

この分け方の価値は、HTTPエラーとクライアント側の例外を同じ失敗として潰さないことです。エラー側ではメッセージとペイロード、例外側ではメッセージと例外オブジェクトへアクセスできます。READMEは`LimitedRequest`や`WrongArgument`のように、既存のErrorまたはExceptionを拡張するカスタム型も示しています。画面表示、再試行、監視、ユーザーへの案内を分岐させるため、API境界でこの三つの意味を維持する設計が重要です。

onSuccessからonFailureまでの処理境界

応答を得た後は、`onSuccess`、`onError`、`onException`、`onFailure`の各スコープを使い、型が一致した場合だけ処理を実行できます。`onFailure`はErrorとExceptionの両方を受けるため、共通の失敗記録を一か所へ置くときに使えます。READMEは、`ApiResponse.of`と`suspendOf`、それらの関数名を持つバリエーションでリクエストラムダを包む方法を説明しています。

グローバルオペレーターやグローバルApiResponseマッパーを使う場合は、グローバル関数が適用されるように`of`または`suspendOf`で作る必要があるという注意があります。ここは単なる書き換えではなく、応答を生成する入口と共通処理の登録方式が結び付く箇所です。ローカルな呼び出しで成功データを表示できても、グローバルログ、エラー変換、認証更新が通る入口かは別に確認します。

suspend関数とFlowへ結果を渡す

コルーチン処理には`suspendOnSuccess`、`suspendOnError`、`suspendOnException`、`suspendOnFailure`があります。スコープ内でDAOへの挿入などのsuspend関数を呼べるため、ネットワーク結果を保存層へ渡す処理を型の分岐に沿って置けます。`toFlow`拡張はApiResponseをコルーチンのFlowへ変換し、データ変換用ラムダを受け取る形もあります。

関数型の拡張には、復帰の`recover`と`recoverWith`、検証の`validate`と`requireNotNull`、フィルタリングの`filter`と`filterNot`、結合の`zip`と`zip3`、観察の`peek`、`peekSuccess`、`peekFailure`、`peekError`、`peekException`が挙げられています。READMEはsuspend版も用意されていると説明します。例のように検証、フィルター、復帰、成功時の観察を連鎖できますが、どの段階で失敗型へ移るか、Flowのキャンセル時に何が保存されるかはアプリのテストで確認します。

再試行と依存リクエストを分ける

再試行は`RetryPolicy`インターフェースの`shouldRetry`と`retryTimeout`で条件を表し、`runAndRetry`拡張がそのポリシーの下でタスクを実行します。READMEの例では最大3回、タイムアウト3,000ミリ秒です。この数字はサンプルポリシーであり、全APIへそのまま適用する既定の安全値ではありません。認証失敗、入力不正、権限不足を同じように再試行すると、負荷や重複処理を増やします。

依存するリクエストは`then`と`suspendThen`で連鎖し、前段の結果を後段へ渡せます。例ではユーザートークン、ユーザー詳細、ポスター情報を順番に取得します。最終値だけ欲しい場合は`getOrNull`、`getOrElse`、`getOrThrow`を使い、成功時はデータを取り出し、失敗時はnull、既定値、Throwableの送出へ分けられます。`getOrThrow`を使うなら呼び出し側のtry/catchとログに秘密情報が出ないことを確認し、再試行回数、待ち時間、冪等性をAPIごとに設計します。

共通オペレーターとトークン更新

`ApiResponseOperator`と`operator`拡張は、成功、エラー、例外の処理を再利用できるプロセッサへまとめます。READMEの`CommonResponseOperator`は、エラーをログへ記録し、`map`でカスタムモデルへ変換し、例外側ではメッセージを残す例です。suspend版では成功スコープからFlowへデータを流す処理も説明されています。

グローバルオペレーターは`SandwichInitializer`へ登録し、アプリ内のApiResponseへ適用できます。`TokenRefreshGlobalOperator`の例は、ヘッダーと401、403のステータスを確認してトークンを更新し、HiltとApp Startupで接続します。この仕組みは共通化に便利ですが、更新処理が無限再帰にならないか、同時リクエストが一つの更新へまとまるか、元のリクエストを何回再送するかを決める必要があります。KtorやKtorfitの一般的なsuspendマッパーとオペレーターは、正しく待機するため`suspendOf`が必要だというREADMEの注意もあります。

Gradle、KMP、R8での配布範囲

Gradleの例では、`com.github.skydoves:sandwich-bom:2.4.0`を使い、コアへ`sandwich`、AndroidのRetrofitへ`sandwich-retrofit`、テストへ`sandwich-test`を追加します。Kotlin Multiplatformでは、共通ソースセットへ`sandwich`、`sandwich-ktor`、`sandwich-ktor-serialization`、`sandwich-ktorfit`とテスト用モジュールを置く構成です。READMEはRetrofit、Ktor、Ktorfit、Testingの公式ドキュメントを入口として案内しています。

R8とProGuardの規則はJARに同梱され、自動で解釈できると説明されています。Pokedex、ChatGPT Android、DisneyMotions、MarvelHeroes、Neko、TheMovies2が利用例として挙げられ、Androidとバックエンドを合わせて120万回以上ダウンロードされたという数値もREADMEの自己報告です。ライセンスはApache-2.0で、保証はありません。バージョン2.4.0を採用する場合も、Kotlin、Gradle、RetrofitまたはKtorの版、R8、例外変換、テストモジュールを組み合わせた自分の環境で確認してから更新します。

編集部の結論

Sandwichは、ネットワークやI/Oの結果をSuccess、Failure.Error、Failure.Exceptionへ統一し、呼び出し側の分岐をKotlinらしいスコープと関数型オペレーターで組み立てたいチームに向きます。Retrofit、Ktor、Ktorfit、Kotlin Multiplatformをまたぐ共通処理や、再試行、トークン更新の置き場所を整理できます。ただし、再試行条件、認証更新、エラーモデル、キャンセル、ログの機密性はアプリ側の責任です。まず一つのAPIで型の境界と失敗時の挙動をテストし、全体へ広げてください。

公式情報源

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
コミュニティノート

コミュニティノート