swagger_generator_flutter/ENUM_KEY_NAMES_USAGE.md

12 KiB
Raw Permalink Blame History

枚举键名配置使用指南

功能说明

生成器支持两种方式生成有意义的枚举键名和注释:

  1. 通过 Swagger 扩展字段(推荐):使用 OpenAPI 扩展字段 x-enum-varnamesx-enum-descriptions
  2. 通过配置文件映射(备选):在 generator_config.yaml 中配置枚举映射

优先级:配置文件映射 > Swagger 扩展字段 > 智能生成

使用方法

方法 1: 在 Swagger 文档中添加扩展字段(推荐)

在枚举定义中添加 x-enum-varnamesx-enum-descriptions 字段:

{
  "components": {
    "schemas": {
      "SysTaskTypeEnums": {
        "enum": [1, 2, 3, 4, 5],
        "type": "integer",
        "description": "任务类型枚举",
        "x-enum-varnames": [
          "SPOT_CHECK",
          "CULTURAL",
          "CLASS_CADRE_MEETING",
          "STUDENT_TALK",
          "FOLLOW_CLASS"
        ],
        "x-enum-descriptions": [
          "抽查",
          "文创建设",
          "班干部会议",
          "学生谈话",
          "双师跟课"
        ]
      }
    }
  }
}

生成结果

有扩展字段时:

/// 任务类型枚举
@JsonEnum()
enum SysTaskTypeEnums {
  /// 抽查
  SPOT_CHECK(1),
  
  /// 文创建设
  CULTURAL(2),
  
  /// 班干部会议
  CLASS_CADRE_MEETING(3),
  
  /// 学生谈话
  STUDENT_TALK(4),
  
  /// 双师跟课
  FOLLOW_CLASS(5),

  /// 未知值
  UNKNOWN(-9999);

  const SysTaskTypeEnums(this.value);
  final int value;

  static SysTaskTypeEnums fromValue(dynamic value) {
    for (final enumValue in SysTaskTypeEnums.values) {
      if (enumValue.value == value) {
        return enumValue;
      }
    }
    return SysTaskTypeEnums.UNKNOWN;
  }

  factory SysTaskTypeEnums.fromJson(dynamic json) {
    return fromValue(json);
  }

  dynamic toJson() => value;
}

没有扩展字段时(向后兼容):

/// 任务类型枚举
@JsonEnum()
enum SysTaskTypeEnums {
  value1(1),
  value2(2),
  value3(3),
  value4(4),
  value5(5),

  /// 未知值
  UNKNOWN(-9999);
  
  // ... 其余代码相同
}

字段说明

x-enum-varnames

  • 类型: string[]
  • 必需: 否
  • 说明: 枚举键名列表,必须与 enum 数组一一对应
  • 要求: 必须是有效的 Dart 标识符(大写字母、下划线)

x-enum-descriptions

  • 类型: string[]
  • 必需: 否
  • 说明: 枚举描述列表,必须与 enum 数组一一对应
  • 要求: 可以是任何字符串,会生成为注释

示例

示例 1: 整数枚举

{
  "SysRoleEnum": {
    "enum": [1, 2, 3, 4],
    "type": "integer",
    "description": "系统角色枚举",
    "x-enum-varnames": ["ADMIN", "TEACHER", "STUDENT", "PARENT"],
    "x-enum-descriptions": ["系统管理员", "教师", "学生", "家长"]
  }
}

生成结果:

/// 系统角色枚举
@JsonEnum()
enum SysRoleEnum {
  /// 系统管理员
  ADMIN(1),
  
  /// 教师
  TEACHER(2),
  
  /// 学生
  STUDENT(3),
  
  /// 家长
  PARENT(4),

  /// 未知值
  UNKNOWN(-9999);
  
  const SysRoleEnum(this.value);
  final int value;
  // ... 其余代码
}

示例 2: 字符串枚举

{
  "ClassTypeEnum": {
    "enum": ["PRIMARY", "MIDDLE", "HIGH"],
    "type": "string",
    "description": "班级类型枚举",
    "x-enum-varnames": ["PRIMARY_SCHOOL", "MIDDLE_SCHOOL", "HIGH_SCHOOL"],
    "x-enum-descriptions": ["小学", "初中", "高中"]
  }
}

生成结果:

/// 班级类型枚举
@JsonEnum()
enum ClassTypeEnum {
  /// 小学
  PRIMARY_SCHOOL('PRIMARY'),
  
  /// 初中
  MIDDLE_SCHOOL('MIDDLE'),
  
  /// 高中
  HIGH_SCHOOL('HIGH'),

  /// 未知值
  UNKNOWN('UNKNOWN');
  
  const ClassTypeEnum(this.value);
  final String value;
  // ... 其余代码
}

示例 3: 只使用 x-enum-varnames

{
  "StatusEnum": {
    "enum": [0, 1, 2],
    "type": "integer",
    "x-enum-varnames": ["PENDING", "ACTIVE", "INACTIVE"]
  }
}

生成结果:

@JsonEnum()
enum StatusEnum {
  PENDING(0),
  ACTIVE(1),
  INACTIVE(2),

  /// 未知值
  UNKNOWN(-9999);
  
  // ... 代码
}

后端实现示例

.NET (Swashbuckle)

public enum SysTaskTypeEnums
{
    [EnumMember(Value = "1")]
    [Description("抽查")]
    SPOT_CHECK = 1,
    
    [EnumMember(Value = "2")]
    [Description("文创建设")]
    CULTURAL = 2,
    
    // ... 更多枚举值
}

// 在 Startup.cs 中配置
services.AddSwaggerGen(c =>
{
    c.SchemaFilter<EnumSchemaFilter>();
});

// EnumSchemaFilter.cs
public class EnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            var enumNames = new List<string>();
            var enumDescriptions = new List<string>();
            
            foreach (var value in Enum.GetValues(context.Type))
            {
                enumNames.Add(value.ToString());
                
                var memberInfo = context.Type.GetMember(value.ToString()).FirstOrDefault();
                var descAttr = memberInfo?.GetCustomAttribute<DescriptionAttribute>();
                enumDescriptions.Add(descAttr?.Description ?? "");
            }
            
            schema.Extensions["x-enum-varnames"] = new OpenApiArray();
            schema.Extensions["x-enum-varnames"].AddRange(
                enumNames.Select(n => new OpenApiString(n))
            );
            
            schema.Extensions["x-enum-descriptions"] = new OpenApiArray();
            schema.Extensions["x-enum-descriptions"].AddRange(
                enumDescriptions.Select(d => new OpenApiString(d))
            );
        }
    }
}

Java (SpringDoc/Swagger)

@Schema(description = "任务类型枚举")
public enum SysTaskTypeEnums {
    @Schema(description = "抽查")
    SPOT_CHECK(1),
    
    @Schema(description = "文创建设")
    CULTURAL(2),
    
    // ... 更多枚举值
    
    private final int value;
    
    SysTaskTypeEnums(int value) {
        this.value = value;
    }
    
    public int getValue() {
        return value;
    }
}

// 配置 SchemaCustomizer
@Bean
public OpenApiCustomizer enumCustomizer() {
    return openApi -> {
        openApi.getComponents().getSchemas().forEach((name, schema) -> {
            if (schema.getEnum() != null) {
                try {
                    Class<?> enumClass = Class.forName("com.example.enums." + name);
                    if (enumClass.isEnum()) {
                        List<String> varNames = new ArrayList<>();
                        List<String> descriptions = new ArrayList<>();
                        
                        for (Object constant : enumClass.getEnumConstants()) {
                            varNames.add(constant.toString());
                            
                            Field field = enumClass.getField(constant.toString());
                            Schema annotation = field.getAnnotation(Schema.class);
                            descriptions.add(annotation != null ? annotation.description() : "");
                        }
                        
                        schema.addExtension("x-enum-varnames", varNames);
                        schema.addExtension("x-enum-descriptions", descriptions);
                    }
                } catch (Exception e) {
                    // Handle exception
                }
            }
        });
    };
}

注意事项

  1. 数组长度必须匹配:

    • x-enum-varnames 的长度必须与 enum 数组长度相同
    • x-enum-descriptions 的长度必须与 enum 数组长度相同
  2. 键名命名规范:

    • 使用大写字母和下划线UPPER_SNAKE_CASE
    • 必须是有效的 Dart 标识符
    • 不能以数字开头
    • 不能使用 Dart 关键字
  3. 向后兼容:

    • 如果没有提供扩展字段,会自动生成 value1, value2
    • 不影响现有项目
  4. OpenAPI 标准:

    • x- 前缀表示扩展字段,符合 OpenAPI 规范
    • 不会影响其他工具对 Swagger 文档的解析

相关资源

常见问题

Q: 如果只提供部分枚举值的键名怎么办?

A: 系统会检查索引是否在范围内。如果某个枚举值没有对应的键名,会使用默认的 valueN 格式。

Q: 可以混用中文和英文吗?

A: x-enum-varnames 必须是有效的 Dart 标识符(推荐使用英文大写+下划线)。
x-enum-descriptions 可以使用任何语言,会生成为注释。

Q: 后端不支持怎么办?

A: 可以:

  1. 使用配置文件映射(推荐):在 generator_config.yaml 中配置枚举映射
  2. 在生成的 Swagger JSON 文件中手动添加扩展字段
  3. 使用中间处理脚本添加扩展字段
  4. 暂时接受 value1, value2 的命名方式

方法 2: 通过配置文件映射(备选)

如果后端不支持 x-enum-varnames 扩展字段,或者您需要覆盖 Swagger 文档中的枚举定义,可以使用配置文件映射。

配置方式

generator_config.yaml 中添加 enum_key_mappings 配置:

generation:
  models:
    # 枚举键名映射配置
    enum_key_mappings:
      SysTaskTypeEnums:
        - value: 1
          name: SPOT_CHECK
          description: 抽查
        - value: 2
          name: CULTURAL
          description: 文创建设
        - value: 3
          name: CLASS_CADRE_MEETING
          description: 班干部会议
      
      SysRoleEnum:
        - value: 1
          name: ADMIN
          description: 系统管理员
        - value: 2
          name: TEACHER
          description: 教师
        - value: 3
          name: STUDENT
          description: 学生
      
      StatusEnum:
        - value: "active"
          name: ACTIVE
          description: 活跃状态
        - value: "inactive"
          name: INACTIVE
          description: 非活跃状态

配置说明

  • 枚举名称: 必须与 Swagger 文档中的枚举名称完全匹配
  • value: 枚举值,可以是数字或字符串,必须与 Swagger 文档中的枚举值匹配
  • name: 枚举键名,必须是有效的 Dart 标识符(大写字母+下划线)
  • description: 枚举描述(可选),会生成为注释

生成结果

使用上述配置后,生成的代码:

/// 任务类型枚举
@JsonEnum()
enum SysTaskTypeEnums {
  /// 抽查
  SPOT_CHECK(1),
  /// 文创建设
  CULTURAL(2),
  /// 班干部会议
  CLASS_CADRE_MEETING(3);

  const SysTaskTypeEnums(this.value);
  final int value;
  // ... 其余代码
}

优先级说明

如果同时存在配置文件映射和 Swagger 扩展字段,优先级为:

  1. 配置文件映射(最高优先级)
  2. x-enum-varnames 扩展字段
  3. 智能生成 valueN 格式

这意味着您可以使用配置文件来覆盖 Swagger 文档中的枚举定义。

使用场景

配置文件映射适用于以下场景:

  1. 后端不支持 OpenAPI 扩展字段
  2. 需要快速修改枚举键名,无需等待后端修改
  3. 需要临时覆盖 Swagger 文档中的枚举定义
  4. 团队内部统一枚举命名规范
  5. 多个项目共享同一个 Swagger 文档,但需要不同的枚举键名

注意事项

  1. 维护成本: 配置文件需要手动维护,当后端枚举值变化时需要同步更新
  2. 推荐方式: 如果后端支持,仍然推荐使用 Swagger 扩展字段,保持单一数据源
  3. 部分映射: 您可以只为部分枚举值配置映射,未配置的枚举值会使用智能生成

更新日期: 2025-11-24
版本: v2.0