Flutterを使いアプリを作るのに、、APIと連携する部分はswaggerから自動生成したいと考え、openapi-generatorを使うことにしました。
ちなみに、Flutterは、始めたばかりでよくわからず、なんとなく動けばいいかくらいでやってます。。
いくつか参考になりそうなページがあったのですが、その中でも、
Flutter Swagger統合が、わかりやすくサンプルコードもあったのでこちらを参考に実装してみました。
試した環境
- Flutter 2.5.3
- Dart 2.14.4
- Swagger 3.0.0
事前準備
通信するAPIを事前に作っておいて、それをローカルで起動します。
URL:http://localhost:31180/user
メソッド:POST
リクエスト:なし
で実行する簡易的なAPIを用意しました。
swaggerも作成します。
実際のswaggerから、今回必要な箇所を抜粋したのが以下です。
openapi: 3.0.0
info:
title: sample
version: '1.0'
description: sample
contact:
name: murapon
servers:
- url: 'http://localhost:31180'
tags:
- name: user
paths:
/user:
post:
operationId: post-user
tags:
- user
summary: ユーザー登録
description: ユーザーを作成し、uuid等を返す
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/response_user_post'
components:
schemas:
response_user_post:
title: response_user_post
description: ユーザー作成APIのレスポンスモデル
type: object
properties:
uuid:
type: string
description: UUID
password:
type: string
description: パスワード
required:
- uuid
- password
ライブラリーのインストール
openapi-generatorインストール
こちらは参考にしたページ通りインストールするだけです。
swaggerからflutter用コードを生成
事前に、静的なページを表示するFlutterアプリは作っていたので、そこに生成しました。
openapi-generator generate -i ./openapi/definitions/sample.yaml -g dart -o ./openapi/generated/client/
で入れられます。
ここも参考ページ通りです。sample.yaml部分は、作ったswaggerファイル名に書き換えてください。
生成したら、
を実行してください。
APIの実行コードの作成
APIを実行するコードは、参考ページのをそのまま使うとエラーになったので、以下のように変えました。
import 'package:openapi/api.dart';
class sample {
test() async {
// ① ベースとなるAPIクライアント生成
var client = ApiClient(basePath: "http://10.0.2.2:31180");
// ヘッダを追加したい場合はクライアントに設定可能
// client.addDefaultHeader("key", "value");
// ② APIクライアントラッパーを生成
// APIレスポンスをモデルに変換してくれる
var api = UserApi(client);
// ③ レスポンスボディのみが欲しい場合は${HTTPメソッド名+パス名}のメソッドをcall
ResponseUserPost user = await api.postUser('');
print(user.toJson());
}
}
まず、①の接続先URLが、localhostになっていたのですが、Androidシミュレータだとうまくいかなったので、
https://sunnyday-travel-aso-6487.ssl-lolipop.jp/programing/flutter/socketexception/
を参考に、10.0.2.2に変えました。
あと、③のapi.healthGet();が、パス名+HTTPメソッド名という並びになってたのですが、実際に生成されたソースを見ると、HTTPメソッド名+パス名という逆順になっていたのでそこを変えました。
(ライブラリーのバージョンの違いによる?)
また、レスポンスボディを取得するのが、valueだとうまくいかず、生成されたソースにあるtoJsonを使うと取得することができました。
APIを実行したい画面を表示しているソースに
Widget build(BuildContext context) {
・・・
try{
var a = new sample();
a.test();
} catch (e) {
print(e.toString());
}
・・・
}
のように書くと、とりあえず動くことを確認できます。
try,catchはなくてもいいのですが、あるとエラーを検出してくれます。
APIで返される項目名や型が、swaggerの定義と違うと処理できないのですが、その時のエラーは、try,catchを使ってないと検出できませんでした。
HTTPステータスコードをチェックしたい時
レスポンス結果だけを取得したい場合は、
ResponseUserPost user = await api.postUser('');
と、postUserを使うとよいのですが、エラー時などにHTTPステータスコードをチェックし処理を変えたい場合は、
ResponseUserPost user = await api.postUserWithHttpInfo('');
と、postUserWithHttpInfoを使うとよいです。
httpステータスは、postUserWithHttpInfo.statusCode、レスポンスの中身は、postUserWithHttpInfo.bodyなどとレスポンス内容を取得できます。
HttpStatusクラスを使って、
ResponseUserPost user = await api.postUserWithHttpInfo('');
if(user.statusCode == HttpStatus.unauthorized) {
// 認証に失敗したらログイン画面へ遷移する
}
などと言った処理も書くことができます。
おまけ
他にもメソッドやら、定数が自動生成されていて、いろいろ使い方ができそうなので見てみるとよいかと思います。初心者でも比較的読みやすいかと思います。