欢迎光临
我们一直在努力

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.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: 在业务代码中直接调用生成的方法。
  • #mermaid-svg-YGcty5AViSlaFeyB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YGcty5AViSlaFeyB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YGcty5AViSlaFeyB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YGcty5AViSlaFeyB .error-icon{fill:#552222;}#mermaid-svg-YGcty5AViSlaFeyB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YGcty5AViSlaFeyB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YGcty5AViSlaFeyB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YGcty5AViSlaFeyB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YGcty5AViSlaFeyB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YGcty5AViSlaFeyB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YGcty5AViSlaFeyB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YGcty5AViSlaFeyB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YGcty5AViSlaFeyB .marker.cross{stroke:#333333;}#mermaid-svg-YGcty5AViSlaFeyB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YGcty5AViSlaFeyB p{margin:0;}#mermaid-svg-YGcty5AViSlaFeyB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-YGcty5AViSlaFeyB .cluster-label text{fill:#333;}#mermaid-svg-YGcty5AViSlaFeyB .cluster-label span{color:#333;}#mermaid-svg-YGcty5AViSlaFeyB .cluster-label span p{background-color:transparent;}#mermaid-svg-YGcty5AViSlaFeyB .label text,#mermaid-svg-YGcty5AViSlaFeyB span{fill:#333;color:#333;}#mermaid-svg-YGcty5AViSlaFeyB .node rect,#mermaid-svg-YGcty5AViSlaFeyB .node circle,#mermaid-svg-YGcty5AViSlaFeyB .node ellipse,#mermaid-svg-YGcty5AViSlaFeyB .node polygon,#mermaid-svg-YGcty5AViSlaFeyB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YGcty5AViSlaFeyB .rough-node .label text,#mermaid-svg-YGcty5AViSlaFeyB .node .label text,#mermaid-svg-YGcty5AViSlaFeyB .image-shape .label,#mermaid-svg-YGcty5AViSlaFeyB .icon-shape .label{text-anchor:middle;}#mermaid-svg-YGcty5AViSlaFeyB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YGcty5AViSlaFeyB .rough-node .label,#mermaid-svg-YGcty5AViSlaFeyB .node .label,#mermaid-svg-YGcty5AViSlaFeyB .image-shape .label,#mermaid-svg-YGcty5AViSlaFeyB .icon-shape .label{text-align:center;}#mermaid-svg-YGcty5AViSlaFeyB .node.clickable{cursor:pointer;}#mermaid-svg-YGcty5AViSlaFeyB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YGcty5AViSlaFeyB .arrowheadPath{fill:#333333;}#mermaid-svg-YGcty5AViSlaFeyB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YGcty5AViSlaFeyB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YGcty5AViSlaFeyB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YGcty5AViSlaFeyB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YGcty5AViSlaFeyB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YGcty5AViSlaFeyB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YGcty5AViSlaFeyB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YGcty5AViSlaFeyB .cluster text{fill:#333;}#mermaid-svg-YGcty5AViSlaFeyB .cluster span{color:#333;}#mermaid-svg-YGcty5AViSlaFeyB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YGcty5AViSlaFeyB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YGcty5AViSlaFeyB rect.text{fill:none;stroke-width:0;}#mermaid-svg-YGcty5AViSlaFeyB .icon-shape,#mermaid-svg-YGcty5AViSlaFeyB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YGcty5AViSlaFeyB .icon-shape p,#mermaid-svg-YGcty5AViSlaFeyB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YGcty5AViSlaFeyB .icon-shape rect,#mermaid-svg-YGcty5AViSlaFeyB .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YGcty5AViSlaFeyB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YGcty5AViSlaFeyB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YGcty5AViSlaFeyB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    输入

    生成

    生成

    生成

    调用

    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 # 或者 dio

    dev_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';

    void main() async {
    // 1. 创建 Service
    final service = Myservice.create(ChopperClient(
    baseUrl: Uri.parse('https://api.example.com'),
    converter: $JsonSerializableConverter(),
    ));

    // 2. 调用 API
    final response = await service.getUser(id: 123);

    if (response.isSuccessful) {
    // 3. 直接获得强类型的 User 对象
    final User? 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);
    }
    */

    class ApiManager {
    late final MyService _service; // 使用 dynamic 或生成的类型

    // 单例模式
    static final ApiManager _instance = ApiManager._internal();
    factory ApiManager() => _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');
    }
    }
    }

    void main() {
    ApiManager().fetchUser(1001);
    }

    在这里插入图片描述

    赞(0)
    未经允许不得转载:171主机测评 » Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址