You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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模板,添加枚举复用逻辑:

  1. 从OpenAPI Generator仓库复制默认的JavaSpring模板到项目目录
  2. 修改model.mustache和enum.mustache,添加枚举去重逻辑:生成枚举前检查是否已有相同值的枚举类存在,若有则直接引用
  3. 在Maven插件中配置templateDirectory指向自定义模板目录

此方案需熟悉Mustache语法,且模板需随OpenAPI Generator版本同步更新,维护成本较高。

方案三:手动映射枚举(不推荐)

手动创建独立的枚举类,通过importMappings配置将Schema中的枚举映射到手动类:

<configOptions>
    <importMappings>RequestTypeKeyEnum=com.yourcompany.enums.RequestTypeKeyEnum</importMappings>
</configOptions>

缺点是每次外部Schema枚举更新时,需手动同步本地枚举类,不符合你避免重复修改的需求。

内容的提问来源于stack exchange,提问作者VeryNice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:03:07