Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

前言
后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做?
- 对着文档,手写 Dart Model 类(容易写错字段类型)。
- 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。
- 当后端修改了字段名,你对着报错修半天。
这是重复劳动的地狱。
swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括:
- Model 类:支持
json_serializable,带fromJson/toJson。 - Service 类:基于
chopper或dio的请求方法。 - Enum:枚举类型的自动映射。
对于 OpenHarmony 应用开发,这种自动化工具能极大减少与后端对接的沟通成本和代码错误率。
一、核心工作流
该插件作为 build_runner 的一部分运行。
- Config: 在
build.yaml或pubspec.yaml中配置 Swagger 源文件位置。 - Fetch/Read: 读取本地或远程的 Swagger 文件。
- Generate: 生成
.swagger.dart,.models.swagger.dart,.enums.swagger.dart。 - Integration: 在业务代码中直接调用生成的方法。
输入
生成
生成
生成
调用
Http 请求
swagger.json
swagger_dart_code_generator
User, Product 模型
RestClient (Dio/Chopper)
Status枚举
OpenHarmony 应用
Server
二、集成与用法详解
2.1 添加依赖
我们需要生成器和运行时库。
dependencies:flutter:sdk: flutter json_annotation: ^4.8.0 chopper: ^7.0.0 # 或者 diodev_dependencies:build_runner: ^2.4.0 swagger_dart_code_generator: ^4.1.1 json_serializable: ^6.7.0 chopper_generator: ^7.0.0 2.2 配置 build.yaml
在项目根目录创建 build.yaml,告诉生成器去哪里找 Swagger 文件。
targets:$default:builders:swagger_dart_code_generator:options:input_folder:"lib/api_docs/"# 存放 json 的目录output_folder:"lib/api_gen/"# 生成代码的目录# 使用 chopper 还是 dio? 默认是 chopper,dio 需要额外配置use_generator: chopper 2.3 下载 Swagger 文件
将后端的 swagger.json 下载到 lib/api_docs/myservice.swagger.json。
2.4 运行生成
flutter pub run build_runner build 生成完毕后,你会在 lib/api_gen/ 下看到 myservice.swagger.dart 等文件。
2.5 使用生成的代码
import'package:chopper/chopper.dart';import'lib/api_gen/myservice.swagger.dart';voidmain()async{// 1. 创建 Servicefinal service =Myservice.create(ChopperClient( baseUrl:Uri.parse('https://api.example.com'), converter: $JsonSerializableConverter(),));// 2. 调用 APIfinal response =await service.getUser(id:123);if(response.isSuccessful){// 3. 直接获得强类型的 User 对象finalUser? user = response.body;print(user?.name);}}
三、OpenHarmony 适配与实战:解决构建与兼容性
3.1 鸿蒙网络库选择
生成的代码通常依赖 chopper 或 dio。
- Chopper: 基于
http包。在纯 Dart 环境和 Flutter Mobile 上表现良好。 - Dio: 功能更强大(拦截器、下载进度)。
适配建议:
在 OpenHarmony 上,两者都能工作。但如果你需要利用鸿蒙特有的网络配置(如安全证书锁定),推荐使用 Dio 模式,因为你可以更方便地拿到底层的 HttpClientAdapter 进行定制(如替换为 dio_http2_adapter 或自定义 adapter)。
修改 build.yaml 切换到 Dio:
swagger_dart_code_generator:options:use_generator: dio 3.2 解决文件名冲突
有时后端的 Swagger 定义里会有 Page、List 这种通用类名,与 Flutter 冲突。
可以在配置中进行重命名映射。
options:replacement_rules:-pattern:"^Page$"replacement:"ApiPage"3.3 CI/CD 集成
在鸿蒙工程的 CI 流水线中,建议:
- 不提交生成代码:将
lib/api_gen/加入.gitignore。 - 构建时生成:在 CI 脚本中先执行
curl下载最新 Swagger JSON,再执行build_runner。这样能确保 App 始终与后端接口保持一致(如果不一致构建会挂)。
四、功能详解:自定义模版
如果默认生成的代码风格不符合团队规范,该插件支持自定义模板。但这通常比较复杂。更简单的方式是利用 include_if_null 等选项微调 JSON 序列化行为。
五、总结
swagger_dart_code_generator 是“契约优先”开发模式的最佳实践工具。它让 API 接口定义成为真理来源(Source of Truth)。
对于 OpenHarmony 开发者:
- 减少手写:让你从繁琐的 JSON 解析中解放出来,专注于鸿蒙 UI 和交互逻辑。
- 类型安全:所有字段都是类型安全的,再也不用担心
String传成int。
最佳实践:
- 版本控制:虽然建议不提交生成文件,但必须提交 Swagger JSON 文件,以便回溯历史接口变更。
- Review 变更:每次后端更新接口后,重新生成代码,利用 Git Diff 查看变动,这有助于前端提前发现潜在的 Breaking Change。
六、完整实战示例
import'package:chopper/chopper.dart';// 假设这是 build_runner 生成的文件// import 'lib/api_gen/my_service.swagger.dart';/* 假定生成的 Service 类定义如下 (由库自动生成): @ChopperApi() abstract class MyService extends ChopperService { @Get(path: '/users/{id}') Future<Response<User>> getUser(@Path('id') int id); static MyService create([ChopperClient? client]) => _$MyService(client); } */classApiManager{ late finalMyService _service;// 使用 dynamic 或生成的类型// 单例模式staticfinalApiManager _instance =ApiManager._internal();factoryApiManager()=> _instance;ApiManager._internal(){// 初始化 Chopper 客户端final chopper =ChopperClient( baseUrl:Uri.parse('https://api.example.com'), converter:JsonConverter(),// 这里通常用 generated $JsonSerializableConverter errorConverter:JsonConverter(), services:[// 注册生成的服务// MyService.create(),], interceptors:[// HttpLoggingInterceptor(), // 日志拦截器]);// 获取服务实例// _service = chopper.getService<MyService>();}Future<void>fetchUser(int id)async{try{/* // 业务调用非常清爽,完全感知不到 HTTP 细节 final response = await _service.getUser(id: id); if (response.isSuccessful) { // body 是强类型的 User 对象 print('User Name: ${response.body?.name}'); } else { print('API Error: ${response.error}'); } */print('API Call (Simulated)');}catch(e){print('Network Exception: $e');}}}voidmain(){ApiManager().fetchUser(1001);}