Swagger Codegen 生成 Dart / Flutter 客户端实战:以 swagger-codegen Petstore 包为例的安装、认证与 API 调用指南
【免费下载链接】swagger-codegenswagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.项目地址: https://gitcode.com/gh_mirrors/sw/swagger-codegen
导读
本文以 swagger-codegen 仓库中实际生成的 Dart 客户端示例(samples/client/petstore/dart/flutter_petstore/swagger/README.md)为主体,完整讲解一个由 Swagger Codegen 的dart生成器产出的 Dart API 客户端包的结构、安装方式、认证配置与调用方法。读完本文,你将掌握如何把这类生成包接入自己的 Dart / Flutter 项目,理解 API Key 与 OAuth 认证在生成代码中的落地方式,并学会通过DartClientCodegen的配置项控制生成产物的名称、版本与枚举处理行为。
生成产物概览:这个包是什么
swagger包是 Swagger Codegen 基于 Petstore 示例服务自动生成的 Dart 客户端库,其元信息记录在生成包的 README 中:
- API 版本:
1.0.0(对应 OpenAPI/Swagger 规格中声明的服务版本) - 构建生成器:
io.swagger.codegen.languages.DartClientCodegen - 示例服务:Swagger Petstore(所有 URL 均以
http://petstore.swagger.io/v2为基准)
生成包在仓库中的实际目录结构如下(目录树):
swagger/ ├── README.md # 本指南对应的生成说明文档 ├── pubspec.yaml # Dart 包清单(name: swagger, version: 1.0.0) ├── git_push.sh # 一键推送到远程仓库的脚本 ├── docs/ # 按 API/模型生成的 Markdown 文档 │ ├── PetApi.md / StoreApi.md / UserApi.md │ └── Amount.md / ApiResponse.md / Category.md / Currency.md / Order.md / Pet.md / Tag.md / User.md └── lib/ ├── api.dart # 库聚合入口 + defaultApiClient ├── api_client.dart # HTTP 客户端:认证、序列化、请求分发 ├── api_helper.dart # 集合格式转换等辅助函数 ├── api_exception.dart # 统一异常类型 ├── api/ # pet_api.dart / store_api.dart / user_api.dart ├── auth/ # authentication / api_key_auth / oauth / http_basic_auth └── model/ # 8 个模型类,均提供 fromJson / toJson这一布局由生成器源码直接决定:DartClientCodegen在processOpts()中注册了api_client.dart、api_exception.dart、api_helper.dart、api.dart、四个 auth 文件、pubspec.yaml、.analysis_options、git_push.sh、.gitignore与README.md等支撑文件,并将模型与 API 模板分别映射为.dart文件(见 DartClientCodegen.java)。
环境要求
README 明确给出生成包的运行前提:
- Dart 1.20.0 或更高版本,或者
- Flutter 0.0.20 或更高版本
实际生成的 pubspec.yaml 只声明了一个外部依赖:
name: swagger version: 1.0.0 description: Swagger API client dependencies: http: '>=0.11.1 <0.12.0'注意http依赖使用宽松区间约束(>=0.11.1 <0.12.0),因此该包可被pub get解析到区间内的任意兼容版本,在接入你自己的项目时无需担心版本冲突。
安装与使用
README 提供了两种接入方式,均通过编辑目标项目的pubspec.yaml完成。
方式一:通过 Git 仓库引入
当生成包发布到 Git 仓库后,在你的项目pubspec.yaml中声明:
name: swagger version: 1.0.0 description: Swagger API client dependencies: swagger: git: https://github.com/GIT_USER_ID/GIT_REPO_ID.git version: 'any'生成包自带的 git_push.sh 正是为"生成代码后推送到自己的 Git 仓库、再以 Git 依赖方式复用"这一工作流准备的发布脚本。示例中的GIT_USER_ID/GIT_REPO_ID是模板占位符,实际使用时请替换为你自己的用户名与仓库名。
方式二:本地路径引入
在本地开发阶段,可直接以路径方式引用生成包的目录:
dependencies: swagger: path: /path/to/swagger将/path/to/swagger替换为swagger包在本机上的实际路径即可。之后在项目根目录执行pub get完成依赖解析。
快速开始:第一个 API 调用
README 以PetApi.addPet为例演示了完整调用流程:先配置认证,再构造请求体,最后调用方法并捕获异常。
import 'package:swagger/api.dart'; // TODO 配置 OAuth2 访问令牌以通过 petstore_auth 授权 // swagger.api.Configuration.accessToken = 'YOUR_ACCESS_TOKEN'; var api_instance = new PetApi(); var body = new Pet(); // Pet | 需要添加到商店的宠物对象 try { api_instance.addPet(body); } catch (e) { print("Exception when calling PetApi->addPet: $e\n"); }代码背后的实现机制
从生成源码看,调用链可拆解为三层:
API 方法层:
PetApi.addPet位于 pet_api.dart,先校验必填参数(body == null时抛出ApiException(400, "Missing required param: body")),再拼接路径/pet、选取application/json作为 Content-Type,声明authNames = ["petstore_auth"],最终委托给ApiClient.invokeAPI。客户端层:
ApiClient.invokeAPI(api_client.dart)依次完成:按authNames注入认证参数 → 拼装 query string → 合并默认请求头 → 根据contentType决定走MultipartRequest还是普通POST/PUT/DELETE/PATCH/GET分发。异常层:HTTP 状态码
>= 400时统一抛出ApiException(statusCode, body),便于上层按业务捕获处理。
关于"更新"与"多表单"等特殊端点
- 上传图片类接口(
uploadFile,POST /pet/{petId}/uploadImage)走multipart/form-data分支,生成代码会自动构造MultipartRequest并携带文件与表单字段; - 删除类接口(如
deletePet)通过.replaceAll("{petId}", petId.toString())在路径中内插路径参数,同时将api_key写入请求头; - 集合查询参数(如
findPetsByStatus的status)经由api_helper.dart中的_convertParametersForCollectionFormat按csv等格式展开为 query 参数。
API 端点一览
所有 URL 均相对于http://petstore.swagger.io/v2。README 中列出了完整的 19 个端点,覆盖三个 API 类:
PetApi
| 方法 | HTTP 请求 | 描述 |
|---|---|---|
| addPet | POST/pet | 向商店添加新宠物 |
| deletePet | DELETE/pet/{petId} | 删除宠物 |
| findPetsByStatus | GET/pet/findByStatus | 按状态查询宠物(支持逗号分隔多值) |
| findPetsByTags | GET/pet/findByTags | 按标签查询宠物 |
| getPetById | GET/pet/{petId} | 按 ID 查找宠物 |
| updatePet | PUT/pet | 更新已有宠物 |
| updatePetWithForm | POST/pet/{petId} | 以表单数据更新宠物 |
| uploadFile | POST/pet/{petId}/uploadImage | 上传图片 |
StoreApi
| 方法 | HTTP 请求 | 描述 |
|---|---|---|
| deleteOrder | DELETE/store/order/{orderId} | 按 ID 删除订单 |
| getInventory | GET/store/inventory | 按状态返回宠物库存 |
| getOrderById | GET/store/order/{orderId} | 按 ID 查询订单 |
| placeOrder | POST/store/order | 下单 |
UserApi
| 方法 | HTTP 请求 | 描述 |
|---|---|---|
| createUser | POST/user | 创建用户 |
| createUsersWithArrayInput | POST/user/createWithArray | 用数组批量创建用户 |
| createUsersWithListInput | POST/user/createWithList | 用列表批量创建用户 |
| deleteUser | DELETE/user/{username} | 删除用户 |
| getUserByName | GET/user/{username} | 按用户名获取用户 |
| loginUser | GET/user/login | 用户登录 |
| logoutUser | GET/user/logout | 用户登出 |
| updateUser | PUT/user/{username} | 更新用户 |
每个端点的参数表、请求/响应示例、错误码说明详见 docs 目录下对应的PetApi.md、StoreApi.md、UserApi.md文档。
模型(Models)
生成包共包含 8 个模型类,每个均对应docs/下一份 Markdown 文档,并实现了fromJson/toJson序列化接口:
- Amount
- ApiResponse
- Category
- Currency
- Order
- Pet
- Tag
- User
模型类的反序列化由ApiClient._deserialize统一处理(api_client.dart):基础类型(String/int/bool/double)走类型转换,模型类型(Pet/Order/User等)走fromJson,List<...>与Map<String, ...>通过正则解析泛型后递归反序列化;任何失败都会包装为ApiException.withInner(500, ...)抛出。
认证(Authorization)
README 文档声明了两种认证方案,生成代码中均有对应实现,且在ApiClient构造时自动注册:
api_key(API Key)
- 类型:API key
- 参数名:
api_key - 位置:HTTP Header
实现位于 api_key_auth.dart:ApiKeyAuth构造时接收location与paramName,applyToParams时按 location 分别注入 query 或 header;若设置了apiKeyPrefix,则以"$apiKeyPrefix $apiKey"的形式携带前缀。在本示例中,ApiClient构造函数将其注册为_authentications['api_key'] = new ApiKeyAuth("header", "api_key")(见 api_client.dart)。README 提示:测试该示例服务时,可直接使用 API keyspecial-key验证授权过滤器。
petstore_auth(OAuth2)
- 类型:OAuth
- Flow:implicit(隐式授权)
- 授权地址:
http://petstore.swagger.io/api/oauth/dialog - Scopes:
write:pets:修改账户中的宠物read:pets:读取你的宠物
实现位于 oauth.dart:OAuth持有一个accessToken,applyToParams时将其以Authorization: Bearer <token>注入请求头,并提供setAccessToken供运行时更新令牌。快速开始示例中被注释掉的swagger.api.Configuration.accessToken = 'YOUR_ACCESS_TOKEN'正是此用途;此外ApiClient还提供了全局便捷方法setAccessToken,会遍历所有已注册认证并将令牌写入所有OAuth实例(api_client.dart)。
认证在请求时按需生效:每个 API 方法都会声明自己的authNames(如addPet声明["petstore_auth"]),invokeAPI通过_updateParamsForAuth只对声明的认证执行applyToParams,若声明了未注册的认证名则抛出ArgumentError(api_client.dart)。
从生成器源码看包的定制能力
DartClientCodegen(DartClientCodegen.java)定义了该生成包的全部可配置项与命名规则,了解它们可以让你在自行生成客户端时精确控制产物:
| CLI 配置项 | 常量名 | 默认值 | 作用 |
|---|---|---|---|
browserClient | BROWSER_CLIENT | true | 是否为浏览器端客户端(传递给模板) |
pubName | PUB_NAME | swagger | 生成的 pubspec 中的包名 |
pubVersion | PUB_VERSION | 1.0.0 | 生成的 pubspec 中的版本号 |
pubDescription | PUB_DESCRIPTION | Swagger API client | 生成的 pubspec 中的描述 |
useEnumExtension | USE_ENUM_EXTENSION | false | 是否启用x-enum-values扩展生成枚举 |
sourceFolder | SOURCE_FOLDER | "" | 生成代码的源目录 |
对应的命令行用法形如:
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ -i petstore.yaml \ -l dart \ -o generated-code/dart \ --additional-properties pubName=my_client,pubVersion=1.0.0,pubDescription="My API client"生成器还定义了一系列类型映射规则(DartClientCodegen.java),可直接印证生成产物中的 Dart 类型来源:
boolean→bool,string/char→String,integer/long/short→intnumber→num,float/double→doublearray/Array→List,map→Mapdate/Date→DateTime,File→MultipartFilebinary与ByteArray暂以String兜底
命名方面,toVarName会把pet_id之类下划线命名转为petId驼峰形式,数字开头补n前缀,Dart 保留字(class、return、switch等)自动追加下划线转义;toModelName对保留字模型名加model_前缀后再驼峰化。枚举值经toEnumVarName将非法字符替换为下划线(数字枚举加Number前缀),并可通过useEnumExtension支持规格中的x-enum-values扩展(见 DartClientCodegen.java)。
包作者与后续查阅
生成包 README 中记录的示例服务维护者为apiteam@swagger.io。进一步查阅每个端点与模型的字段级说明,请直接浏览 docs 目录下的 Markdown 文档;若要查看 Flutter 工程形态的完整示例(含 iOS/Android 工程骨架),可参考同目录的上层示例 flutter_petstore;而生成该 Dart 包的其余两个变体(swagger与swagger-browser-client)位于 dart 下,可作为对比学习资料。
【免费下载链接】swagger-codegenswagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.项目地址: https://gitcode.com/gh_mirrors/sw/swagger-codegen
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考