swagger_generator_flutter/ENUM_KEY_NAMES_USAGE.md

499 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 枚举键名配置使用指南
## 功能说明
生成器支持两种方式生成有意义的枚举键名和注释:
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>();
});
// 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)
```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<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 文档的解析
## 相关资源
- [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