如何通过OpenAPI Generator Maven插件提取枚举为独立可复用类
解决OpenAPI Generator重复枚举生成问题的方案
针对你遇到的外部提供的OpenAPI Schema生成重复内部枚举的问题,以下是几种无需手动修改原Schema的可行方案:
方案一:自动化预处理OpenAPI Schema(推荐)
通过脚本自动识别Schema中重复的枚举定义,将其提取为可复用的components/schemas节点,再替换原枚举为$ref引用,最后用处理后的Schema生成代码。完全自动化,无需手动维护。
步骤1:编写预处理脚本
用Python写一个简单的脚本,遍历Schema中的所有枚举,合并相同值的枚举并生成引用:
import yaml from collections import defaultdict def process_openapi_yaml(input_path, output_path): with open(input_path, 'r') as f: spec = yaml.safe_load(f) # 收集所有枚举:键为(类型, 枚举值元组),值为枚举的属性名、定义等信息 enum_map = defaultdict(list) # 遍历所有Schema属性,收集枚举 def traverse_schema(schema): if 'properties' in schema: for prop_name, prop_schema in schema['properties'].items(): if 'enum' in prop_schema and 'type' in prop_schema: enum_key = (prop_schema['type'], tuple(prop_schema['enum'])) enum_map[enum_key].append({ 'prop_name': prop_name, 'schema': prop_schema, 'desc': prop_schema.get('description', '') }) # 处理嵌套结构 if 'items' in prop_schema: traverse_schema(prop_schema['items']) if 'allOf' in prop_schema: for sub_schema in prop_schema['allOf']: if '$ref' in sub_schema: ref_name = sub_schema['$ref'].split('/')[-1] traverse_schema(spec['components']['schemas'][ref_name]) else: traverse_schema(sub_schema) # 遍历components中的所有Schema for schema in spec.get('components', {}).get('schemas', {}).values(): traverse_schema(schema) # 遍历路径中的请求/响应Schema for path in spec.get('paths', {}).values(): for op in path.values(): for content in op.get('requestBody', {}).get('content', {}).values(): if '$ref' in content.get('schema', {}): ref_name = content['schema']['$ref'].split('/')[-1] traverse_schema(spec['components']['schemas'][ref_name]) for resp in op.get('responses', {}).values(): for content in resp.get('content', {}).values(): if '$ref' in content.get('schema', {}): ref_name = content['schema']['$ref'].split('/')[-1] traverse_schema(spec['components']['schemas'][ref_name]) # 生成复用的枚举Schema并替换原定义 spec['components']['schemas'] = spec.get('components', {}).get('schemas', {}) for (enum_type, enum_values), entries in enum_map.items(): if len(entries) > 1: # 用第一个属性名作为枚举类名(可自定义命名规则) enum_name = entries[0]['prop_name'] + 'Enum' # 创建枚举Schema enum_schema = { 'type': enum_type, 'enum': list(enum_values), 'description': entries[0]['desc'] } spec['components']['schemas'][enum_name] = enum_schema # 替换所有重复枚举为引用 for entry in entries: del entry['schema']['enum'] del entry['schema']['type'] entry['schema']['$ref'] = f'#/components/schemas/{enum_name}' # 写入处理后的Schema with open(output_path, 'w') as f: yaml.dump(spec, f, sort_keys=False) if __name__ == '__main__': process_openapi_yaml('src/main/resources/original-openapi.yaml', 'target/processed-openapi.yaml')
步骤2:配置Maven构建流程
在pom.xml中添加插件,先执行预处理脚本,再用处理后的Schema生成代码:
<build> <plugins> <!-- 预处理OpenAPI Schema --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>process-enums</id> <phase>generate-sources</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>python</executable> <arguments> <argument>scripts/process_enums.py</argument> <argument>src/main/resources/original-openapi.yaml</argument> <argument>target/processed-openapi.yaml</argument> </arguments> </configuration> </execution> </executions> </plugin> <!-- 生成Spring代码 --> <plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>6.6.0</version> <executions> <execution> <id>generate-spring-code</id> <phase>generate-sources</phase> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.build.directory}/processed-openapi.yaml</inputSpec> <generatorName>spring</generatorName> <configOptions> <modelPackage>com.yourcompany.model</modelPackage> <apiPackage>com.yourcompany.api</apiPackage> <useSpringBoot3>true</useSpringBoot3> </configOptions> </configuration> </execution> </executions> </plugin> </plugins> </build>
方案二:自定义OpenAPI Generator模板
修改Spring生成器的Mustache模板,添加枚举复用逻辑:
- 从OpenAPI Generator仓库复制默认的JavaSpring模板到项目目录
- 修改
model.mustache和enum.mustache,添加枚举去重逻辑:生成枚举前检查是否已有相同值的枚举类存在,若有则直接引用 - 在Maven插件中配置
templateDirectory指向自定义模板目录
此方案需熟悉Mustache语法,且模板需随OpenAPI Generator版本同步更新,维护成本较高。
方案三:手动映射枚举(不推荐)
手动创建独立的枚举类,通过importMappings配置将Schema中的枚举映射到手动类:
<configOptions> <importMappings>RequestTypeKeyEnum=com.yourcompany.enums.RequestTypeKeyEnum</importMappings> </configOptions>
缺点是每次外部Schema枚举更新时,需手动同步本地枚举类,不符合你避免重复修改的需求。
内容的提问来源于stack exchange,提问作者VeryNice
相关产品推荐
相关产品推荐

