# 枚举键名配置使用指南 ## 功能说明 生成器支持两种方式生成有意义的枚举键名和注释: 1. **通过 Swagger 扩展字段**(推荐):使用 OpenAPI 扩展字段 `x-enum-varnames` 和 `x-enum-descriptions` 2. **通过配置文件映射**(备选):在 `generator_config.yaml` 中配置枚举映射 **优先级**:配置文件映射 > Swagger 扩展字段 > 智能生成 ## 使用方法 ### 方法 1: 在 Swagger 文档中添加扩展字段(推荐) 在枚举定义中添加 `x-enum-varnames` 和 `x-enum-descriptions` 字段: ```json { "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": [ "抽查", "文创建设", "班干部会议", "学生谈话", "双师跟课" ] } } } } ``` ### 生成结果 **有扩展字段时**: ```dart /// 任务类型枚举 @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; } ``` **没有扩展字段时(向后兼容)**: ```dart /// 任务类型枚举 @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: 整数枚举 ```json { "SysRoleEnum": { "enum": [1, 2, 3, 4], "type": "integer", "description": "系统角色枚举", "x-enum-varnames": ["ADMIN", "TEACHER", "STUDENT", "PARENT"], "x-enum-descriptions": ["系统管理员", "教师", "学生", "家长"] } } ``` 生成结果: ```dart /// 系统角色枚举 @JsonEnum() enum SysRoleEnum { /// 系统管理员 ADMIN(1), /// 教师 TEACHER(2), /// 学生 STUDENT(3), /// 家长 PARENT(4), /// 未知值 UNKNOWN(-9999); const SysRoleEnum(this.value); final int value; // ... 其余代码 } ``` ### 示例 2: 字符串枚举 ```json { "ClassTypeEnum": { "enum": ["PRIMARY", "MIDDLE", "HIGH"], "type": "string", "description": "班级类型枚举", "x-enum-varnames": ["PRIMARY_SCHOOL", "MIDDLE_SCHOOL", "HIGH_SCHOOL"], "x-enum-descriptions": ["小学", "初中", "高中"] } } ``` 生成结果: ```dart /// 班级类型枚举 @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 ```json { "StatusEnum": { "enum": [0, 1, 2], "type": "integer", "x-enum-varnames": ["PENDING", "ACTIVE", "INACTIVE"] } } ``` 生成结果: ```dart @JsonEnum() enum StatusEnum { PENDING(0), ACTIVE(1), INACTIVE(2), /// 未知值 UNKNOWN(-9999); // ... 代码 } ``` ## 后端实现示例 ### .NET (Swashbuckle) ```csharp public enum SysTaskTypeEnums { [EnumMember(Value = "1")] [Description("抽查")] SPOT_CHECK = 1, [EnumMember(Value = "2")] [Description("文创建设")] CULTURAL = 2, // ... 更多枚举值 } // 在 Startup.cs 中配置 services.AddSwaggerGen(c => { c.SchemaFilter(); }); // EnumSchemaFilter.cs public class EnumSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (context.Type.IsEnum) { var enumNames = new List(); var enumDescriptions = new List(); foreach (var value in Enum.GetValues(context.Type)) { enumNames.Add(value.ToString()); var memberInfo = context.Type.GetMember(value.ToString()).FirstOrDefault(); var descAttr = memberInfo?.GetCustomAttribute(); 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) ```java @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 varNames = new ArrayList<>(); List 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 文档的解析 ## 相关资源 - [OpenAPI 扩展字段规范](https://swagger.io/docs/specification/openapi-extensions/) - [OpenAPI Generator 枚举支持](https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md#enum) - [示例 Swagger 文档](./example/swagger_enum_example.json) ## 常见问题 ### 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` 配置: ```yaml 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**: 枚举描述(可选),会生成为注释 ### 生成结果 使用上述配置后,生成的代码: ```dart /// 任务类型枚举 @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