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

如何基于swagger.json生成curl、GO、Node.js、Java格式的API请求代码

基于swagger.json生成多语言接口请求代码的落地方案

核心实现逻辑

  • 首先完成swagger/OpenAPI规范的结构解析,提取接口全量字段:包括服务根地址、接口路径、请求方法、各类参数(path路径参数、query查询参数、header请求头、body请求体)、请求内容类型、示例值等
  • 预先定义4种目标语言的请求代码模板,预留通用占位符(如请求地址、请求头、请求体、方法名等),无需硬编码逻辑
  • 将解析得到的结构化接口参数,适配后填充到对应模板的占位符中,自动完成代码渲染
  • 做异常兼容处理,覆盖swagger定义不完整、多版本规范差异等边界场景

具体实现步骤

1. 依赖选择

优先选择成熟的解析和模板渲染工具,避免手写schema校验和字符串拼接逻辑,可根据技术栈二选一:

  • Python技术栈:用openapi-spec-validator做swagger合法性校验&结构解析,兼容OpenAPI2.0/3.0版本,用jinja2做模板渲染
  • Node.js技术栈:用swagger-parser做swagger解析,用handlebars/ejs做模板渲染

2. 核心解析逻辑示例(Python版)

from openapi_spec_validator import validate_spec
from openapi_spec_validator.readers import read_from_filename
import json

# 读取并校验swagger文件合法性
spec_dict, _ = read_from_filename("swagger.json")
validate_spec(spec_dict)

# 提取全局配置
base_url = ""
if "openapi" in spec_dict and spec_dict["openapi"].startswith("3"):
    # OpenAPI3.0 取servers配置
    base_url = spec_dict.get("servers", [{"url": ""}])[0].get("url", "")
else:
    # Swagger2.0 取basePath + host + schemes
    host = spec_dict.get("host", "")
    base_path = spec_dict.get("basePath", "")
    schemes = spec_dict.get("schemes", ["http"])[0]
    base_url = f"{schemes}://{host}{base_path}"

paths = spec_dict.get("paths", {})
api_list = []

# 遍历所有接口提取结构化信息
for path, path_info in paths.items():
    for method, op_info in path_info.items():
        # 过滤非请求方法字段
        if method not in ["get", "post", "put", "delete", "patch", "head", "options"]:
            continue
        # 提取接口基础信息
        api_item = {
            "name": op_info.get("summary", f"{method}_{path.replace('/', '_')}"),
            "method": method,
            "path": path,
            "path_params": [],
            "query_params": [],
            "header_params": [],
            "body": None,
            "content_type": "application/json"
        }
        # 拆分各类参数
        for param in op_info.get("parameters", []):
            param_type = param.get("in")
            if param_type == "path":
                api_item["path_params"].append(param)
            elif param_type == "query":
                api_item["query_params"].append(param)
            elif param_type == "header":
                api_item["header_params"].append(param)
        # 提取请求体
        if "requestBody" in op_info:
            content = op_info["requestBody"].get("content", {})
            # 优先取json格式的请求体
            if "application/json" in content:
                api_item["content_type"] = "application/json"
                api_item["body"] = content["application/json"].get("example", {})
        # 拼接完整请求地址,替换路径参数占位符
        full_path = path
        for p in api_item["path_params"]:
            full_path = full_path.replace(f"{{{p['name']}}}", str(p.get("example", "test_value")))
        # 拼接query参数
        if api_item["query_params"]:
            query_str = "&".join([f"{p['name']}={p.get('example', 'test_value')}" for p in api_item["query_params"]])
            full_path += f"?{query_str}"
        api_item["full_url"] = f"{base_url}{full_path}"
        api_list.append(api_item)

解析后得到的api_list就是标准化的接口结构化数据,可直接用于后续模板渲染。

3. 多语言模板示例(jinja2语法)

所有模板统一使用解析得到的api_item字段填充,修改模板即可调整生成代码的格式,无需改动解析逻辑。

3.1 Curl模板

curl -X {{api_item.method|upper}} \
{% for header in api_item.header_params %}  -H '{{header.name}}: {{header.get("example", "test_value")}}' \
{% endfor %}
-H 'Content-Type: {{api_item.content_type}}' \
{% if api_item.body %}  -d '{{api_item.body|tojson}}' \
{% endif %}
'{{api_item.full_url}}'

3.2 Go代码模板(基于net/http)

package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
	"strings"
)

func main() {
	url := "{{api_item.full_url}}"
	{% if api_item.body %}payload := strings.NewReader(`{{api_item.body|tojson}}`){% else %}payload := nil{% endif %}
	req, err := http.NewRequest("{{api_item.method|upper}}", url, payload)
	if err != nil {
		panic(err)
	}
	{% for header in api_item.header_params %}req.Header.Add("{{header.name}}", "{{header.get('example', 'test_value')}}")
	{% endfor %}
	req.Header.Add("Content-Type", "{{api_item.content_type}}")

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
}

3.3 Node.js代码模板(基于axios)

const axios = require('axios');

async function {{api_item.name.replace(/\s+/g, '_').toLowerCase()}}() {
  const config = {
    method: '{{api_item.method}}',
    url: '{{api_item.full_url}}',
    headers: {
      {% for header in api_item.header_params %}'{{header.name}}': '{{header.get('example', 'test_value')}}',
      {% endfor %}
      'Content-Type': '{{api_item.content_type}}'
    }{% if api_item.body %},
    data: {{api_item.body|tojson}}{% endif %}
  };
  const res = await axios(config);
  console.log(res.data);
}

{{api_item.name.replace(/\s+/g, '_').toLowerCase()}}();

3.4 Java代码模板(基于JDK11+原生HttpClient)

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class {{api_item.name.replace(/\s+/g, '')|capitalize}} {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create("{{api_item.full_url}}"));
        // 填充请求头
        {% for header in api_item.header_params %}builder.header("{{header.name}}", "{{header.get('example', 'test_value')}}");
        {% endfor %}
        builder.header("Content-Type", "{{api_item.content_type}}");
        // 填充请求方法&请求体
        {% if api_item.method|upper == 'GET' %}builder.GET();
        {% elif api_item.body %}builder.{{api_item.method|upper}}(HttpRequest.BodyPublishers.ofString("{{api_item.body|tojson|escapejs}}"));
        {% else %}builder.{{api_item.method|upper}}(HttpRequest.BodyPublishers.noBody());
        {% endif %}
        HttpRequest request = builder.build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}

4. 代码渲染输出

将每个接口的api_item对象传入对应模板渲染后,可按需求输出:

  • 每个接口单独生成4个代码文件,按语言分类存放
  • 统一生成一个Markdown文档,每个接口下挂载4种语言的代码块,方便查阅

可选优化点

  • 自动填充参数示例值:优先取swagger中定义的example字段,无定义时按参数类型生成默认值(string类型填"demo",number类型填1,boolean类型填true)
  • 支持批量导出:可添加命令行参数,自定义swagger文件路径、输出目录、需要生成的语言类型
  • 兼容特殊场景:支持form-data、x-www-form-urlencoded等非json格式的请求体生成

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:24:10