🌐

openapi_generator使ってみた

2025/02/07に公開

Note(ノート)

openapi_generatorがよく使われているのが流行りかなと思い勉強してみました。dioを使用してAPI通信するコードを自動生成してくれる便利なものですね。

https://pub.dev/packages/openapi_generator

This library is the dart/flutter implementation of openapi client sdk code generation.

With this library, you can generate openapi client sdk libraries from your openapi specification right in your flutter/dart projects. (see example)

To be used together with openapi-generator-annotations


このライブラリはopenapiクライアントSDKコード生成のdart/flutter実装です。

このライブラリを使うと、openapi仕様からopenapiクライアントSDKライブラリをflutter/dartプロジェクト内で生成することができます。

こちらが完成品

developブランチバージョンもあります。

openapi-generator-annotationと一緒に使うライブラリ

他にもその他多数あります。

https://pub.dev/packages/openapi_generator
https://pub.dev/packages/openapi_generator_annotations

pathなるものはファイルを自動生成した後に追加する。

openapi:
    path: ./api  # 生成されたapiフォルダへのパスを追加

settings file

試行錯誤して作ったのでバージョン古いの混ざってるかも?

公式のファイルだと複雑でわからなかった(^_^;)
https://github.com/gibahjoe/openapi-generator-dart/blob/master/example/pubspec.yaml

pubspec.yaml
name: open_generator_sample
description: "A new Flutter project."

publish_to: 'none'

version: 1.0.0+1

environment:
  sdk: ^3.6.1

dependencies:
  built_collection: ^5.1.1
  flutter:
    sdk: flutter
  openapi_generator_annotations: ^6.1.0
  dio: ^5.4.1
  json_annotation: ^4.9.0
  
  cupertino_icons: ^1.0.8
  openapi:
    path: ./api  # 生成されたapiフォルダへのパスを追加

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: ^2.4.14
  openapi_generator: ^6.1.0
  json_serializable: ^6.7.1
  
  flutter_lints: ^5.0.0

flutter:

  uses-material-design: true

このエンドポイントのJSONをYAMLで書く
https://jsonplaceholder.typicode.com/posts

openapi.yamlを作成する。

openapi: 3.0.0
info:
  title: Post API
  version: 1.0.0
  description: API for managing posts

servers:
  - url: https://jsonplaceholder.typicode.com
    description: JSONPlaceholder API

paths:
  /posts:
    get:
      summary: Get all posts
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Post'
    
  /posts/{id}:
    get:
      summary: Get a post by ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Post'

components:
  schemas:
    Post:
      type: object
      properties:
        userId:
          type: integer
        id:
          type: integer
        title:
          type: string
        body:
          type: string
      required:
        - userId
        - id
        - title
        - body 

configファイルを作成する。

// Openapi Generator last run: : 2025-02-07T18:36:57.311673
import 'package:openapi_generator_annotations/openapi_generator_annotations.dart';

// Openapi Generatorの設定
(
  additionalProperties: AdditionalProperties(
    pubName: 'openapi', // 生成するパッケージ名
    pubAuthor: 'Your Name', // 生成するパッケージの作者名
  ),
  inputSpec: InputSpec(path: 'openapi.yaml'), // 生成するAPIの設定ファイル
  generatorName: Generator.dio, // 生成するAPIのライブラリ
  outputDirectory: 'api', // 生成するAPIのディレクトリ
)

// 生成するAPIの設定
class ApiConfig {
  static const String baseUrl = 'https://jsonplaceholder.typicode.com';
}

ファイルを自動生成する:

flutter pub run build_runner watch --delete-conflicting-outputs

HTTP GETを早速やってみよう。

main.dart
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:openapi/openapi.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final api = DefaultApi(
    Dio()..options.baseUrl = 'https://jsonplaceholder.typicode.com',
    standardSerializers,
  );

  Future<List<Post>> fetchPosts() async {
    final response = await api.postsGet();
    return response.data!.toList();
  }

  
  void initState() {
    super.initState();
    fetchPosts();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: FutureBuilder<List<Post>>(
        future: fetchPosts(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }

          if (snapshot.hasError) {
            return Center(child: Text('エラー: ${snapshot.error}'));
          }

          final posts = snapshot.data!;
          return ListView.builder(
            itemCount: posts.length,
            itemBuilder: (context, index) {
              final post = posts[index];
              return ListTile(
                title: Text(post.title),
                subtitle: Text(post.body),
              );
            },
          );
        },
      ),
    );
  }
}

Que(きっかけ)

昔仕事で使ったことあったので個人的に使ってみたいなと思って試してみた。
フィットネスアプリを開発する案件で使われていてこれどうなってるんだろう???
当時はさっぱりわからなかった。既存のコードはyamlファイルに定義されているスキーマー通りに自動生成されるのでただ使うだけでよかった。

いやー難しい(^_^;)

Swagger Viewerというのもあるので試してみてね。yamlファイルで Shift + Alt + P

https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer


Summary(要約)

https://swagger.io/specification/

OpenAPI仕様(OAS)は、HTTP APIのための標準的な言語に依存しないインターフェースを定義するものです。これにより、ソースコード、ドキュメント、またはネットワークトラフィックの検査なしでも、人間とコンピュータの両方がサービスの機能を発見し理解することができます。適切に定義されていれば、利用者は最小限の実装ロジックで、リモートサービスを理解し、相互作用することができます。
OpenAPI定義は以下のような様々な用途に活用できます:

  • ドキュメント生成ツールによるAPI仕様の表示
  • 様々なプログラミング言語でのサーバーやクライアントコードの自動生成
  • テストツールでの利用
  • その他多くのユースケース

Discussion