NSwagは、.NETベースのオープンソースツールであり、OpenAPI(Swagger)仕様をもとに型安全なクライアントコードを多言語で自動生成する機能を提供します。特に、IBM i上で動作するRPG/400系レガシーアプリケーションを現代的なWebサービスとして公開・連携する際、そのAPIインターフェースを正確かつ効率的に抽象化・利用可能にするための鍵となるツールです。
なぜNSwagがIBM i統合に適しているか
RPGプログラムからRESTfulエンドポイントを公開する場合、手動でのクライアント実装はスキーマ変更への脆弱性や型不整合のリスクを伴います。NSwagは以下の特性により、この課題を解消します:
- アセンブリ駆動型生成:ASP.NET Core Web APIプロジェクト(例:RPGから呼び出される.NET中間層)のDLLを直接読み込み、コントローラー定義からOpenAPIドキュメントを逆生成
- 言語横断対応:TypeScript(ES2020+)、C#(.NET 6+)、Python(HTTPXベース)など、複数ターゲットのクライアントを一括生成可能
- カスタム型マッピング:RPG特有の固定長文字列(例:
CHAR(10))やゾーンデシマル数値を、JSONスキーマレベルでformatやpattern属性で制約付与可能 - CI/CD統合性:
nswag.json設定ファイルとCLIツールを組み合わせることで、ビルドパイプラインにクライアント再生成ステップを容易に組み込める
実践ワークフロー:RPG連携向けクライアント構築手順
前提条件の整備
- .NET SDK 6.0+ および Node.js 18+ をインストール
- RPGプログラムをラップする.NET Web APIプロジェクト(例:
IbmIAdapter.Api)を用意し、[ApiController]付きエンドポイントを実装 - 該当プロジェクトの出力アセンブリ(
bin/Release/net6.0/IbmIAdapter.Api.dll)が利用可能であることを確認
NSwagStudioによるGUIベース生成(開発初期段階向け)
NSwagStudioを起動後、以下設定を適用:
- Input → Web API Assembly タブを選択
Assembly pathに上記DLLパスを指定Controller nameにRPG対応エンドポイントを含むコントローラー名(例:RpgDataController)を入力Swagger generation settingsでUse controller and action names as operation idsを有効化(可読性向上)Generate Outputsをクリック →swagger.jsonが出力される
TypeScriptクライアント生成(React/Vueアプリ向け)
同一UIでTypeScript Clientタブへ移動し、次のように設定:
{
"moduleName": "IbmIRpgClient",
"className": "RpgServiceClient",
"template": "fetch",
"useTransformers": true,
"generateOptionalParameters": false,
"generateResponseClasses": true,
"output": "../src/generated/rpg-client.ts"
}
生成されたクライアントは、fetch APIを基盤とし、Zodによるレスポンスバリデーションを追加可能。RPG由来の日付フォーマット(例:"YYYYMMDD")には、transformRequestオプションで前処理関数を注入できます。
C#クライアント生成(.NETバックエンド向け)
CSharp Clientタブで以下を指定:
Namespace:Company.Integration.IbmIClient base class:System.Net.Http.HttpClient(既存DIコンテナとの互換性確保)Generate contracts:true(DTOクラスの明示的生成)Use DTOs for responses:true(非同期メソッドの戻り値をTask<ApiResponse<T>>形式に統一)
生成結果は、HttpClientFactoryと併用することで、依存性注入経由で安全に利用可能です。
高度なカスタマイズ技法
テンプレート拡張によるRPG固有ロジックの埋め込み
NSwagのLiquidテンプレートを修正して、RPG由来のエラー応答(例:{"rc": 404, "msg": "レコード不存在"})を共通ハンドラに紐づけることができます。テンプレート内では、{{operation.StatusCode}}や{{operation.Responses["200"].Schema.Type}}などのコンテキスト変数が利用可能です。
CLIによるCI環境連携
GitHub Actionsでの自動化例:
# .github/workflows/generate-clients.yml
- name: Generate TypeScript client
run: |
dotnet tool install --global NSwag.ConsoleCore
nswag openapi2tsclient /input:./swagger.json /output:./src/generated/client.ts /template:fetch
RPGデータ型のマッピング最適化
OpenAPI仕様にx-rpg-type拡張プロパティを追加し、NSwagのOperationProcessorでこれを検知して、生成コードにRPG互換のパーサーを挿入できます。例えば、"x-rpg-type": "zoned-decimal"を持つフィールドに対しては、decimal.Parse(value, new NumberFormatInfo { ... })を自動生成するようにカスタマイズ可能です。