java yaml api,Swagger (YAML OpenAPI) 从放弃到入门

Swagger是一个基于YAML或JSON的API描述工具,用于生成代码和文档。YAML因其简洁性而被推荐。本文介绍了YAML的基本语法,并详细解释了OpenAPI规范,它定义了RESTful APIs的标准接口。通过符合OpenAPI规范的描述文件,可以生成多种语言和库的代码、文档和工具。示例展示了Uber API的OpenAPI规范,包括产品类型、价格估计和时间估计等API接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Swagger 是一个统一前后端用于生成文档和代码的工具,它使用 yaml / json 作为描述语言 通过 OpenAPI Specification 来描述 API,最后使用 Codegen 根据不同的配置来生成各种 language、library 的 Code、Docs.

其最理想的情况则是只需一份描述文件(yaml/json) 生成 后端、前端(android ios web...)的代码和文档,这样的话保证了前后端的统一,且需要升级改动也只需要修改 yaml 文件。

YAML

JSON 都已经很熟悉了,虽然 Swagger 可以使用 JSON 作为描述语言,但是因为 YAML 更为简洁直观,所以更推荐 YAML。

YAML 的基本语法并不复杂,这里介绍一些基本语法:

yaml 文件 以---开始 ...结尾

同一级别的成员(如 list 成员)可以通过"- "来辨识

注释以#开头的一行

list:

fruits:

- Apple

- Orange

- Strawberry

- Mango

key / value

martin:

name: Martin D'vloper

job: Developer

skill: Elite

list / map 混合使用

- martin:

name: Martin D'vloper

job: Developer

skills:

- python

- perl

- pascal

- tabitha:

name: Tabitha Bitumen

job: Developer

skills:

- lisp

- fortran

- erlang

list / map 的简写

martin: {name: Martin D'vloper, job: Developer, skill: Elite}

fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']

boolean 值的写法没有严格限制

create_key: yes

needs_agent: no

knows_oop: True

likes_emacs: TRUE

uses_cvs: false

|使用换行 >忽略换行

include_newlines: |

exactly as you see

will appear these three

lines of poetry

ignore_newlines: >

this is really a

single line of text

despite appearances

OpenAPI-Specification

OpenAPI 是一套用于描述 RESTful APIs 的规范。

The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to RESTful APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined, a consumer can understand and interact with the remote service with a minimal amount of implementation logic.

An OpenAPI definition can then be used by documentation generation tools to display the API, code generation tools to generate servers and clients in various programming languages, testing tools, and many other use cases.

只要符合 OpenAPI 规范的都可以生成各类代码、文档、工具。

目前 OpenAPI 最新 3.0.0 ,对比 2.0 对 API 结构进行了调整。

文档内容繁多请参考 OpenAPI-Specification 3.0.0

下面是 Uber API 的 example

# this is an example of the Uber API

# as a demonstration of an API spec in YAML

openapi: "3.0.0"

info:

title: Uber API

description: Move your app forward with the Uber API

version: "1.0.0"

servers:

- url: https://api.uber.com/v1

paths:

/products:

get:

summary: Product Types

description: The Products endpoint returns information about the Uber products offered at a given location. The response includes the display name and other details about each product, and lists the products in the proper display order.

parameters:

- name: latitude

in: query

description: Latitude component of location.

required: true

schema:

type: number

format: double

- name: longitude

in: query

description: Longitude component of location.

required: true

schema:

type: number

format: double

security:

- apikey: []

tags:

- Products

responses:

'200':

description: An array of products

content:

application/json:

schema:

$ref: "#/components/schemas/ProductList"

default:

description: Unexpected error

content:

application/json:

schema:

$ref: "#/components/schemas/Error"

/estimates/price:

get:

summary: Price Estimates

description: The Price Estimates endpoint returns an estimated price range for each product offered at a given location. The price estimate is provided as a formatted string with the full price range and the localized currency symbol.
The response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code for situations requiring currency conversion. When surge is active for a particular product, its surge_multiplier will be greater than 1, but the price estimate already factors in this multiplier.

parameters:

- name: start_latitude

in: query

description: Latitude component of start location.

required: true

schema:

type: number

format: double

- name: start_longitude

in: query

description: Longitude component of start location.

required: true

schema:

type: number

format: double

- name: end_latitude

in: query

description: Latitude component of end location.

required: true

schema:

type: number

format: double

- name: end_longitude

in: query

description: Longitude component of end location.

required: true

schema:

type: number

format: double

tags:

- Estimates

responses:

'200':

description: An array of price estimates by product

content:

application/json:

schema:

type: array

items:

$ref: "#/components/schemas/PriceEstimate"

default:

description: Unexpected error

content:

application/json:

schema:

$ref: "#/components/schemas/Error"

/estimates/time:

get:

summary: Time Estimates

description: The Time Estimates endpoint returns ETAs for all products offered at a given location, with the responses expressed as integers in seconds. We recommend that this endpoint be called every minute to provide the most accurate, up-to-date ETAs.

parameters:

- name: start_latitude

in: query

description: Latitude component of start location.

required: true

schema:

type: number

format: double

- name: start_longitude

in: query

description: Longitude component of start location.

required: true

schema:

type: number

format: double

- name: customer_uuid

in: query

schema:

type: string

format: uuid

description: Unique customer identifier to be used for experience customization.

- name: product_id

in: query

schema:

type: string

description: Unique identifier representing a specific product for a given latitude & longitude.

tags:

- Estimates

responses:

'200':

description: An array of products

content:

application/json:

schema:

type: array

items:

$ref: "#/components/schemas/Product"

default:

description: Unexpected error

content:

application/json:

schema:

$ref: "#/components/schemas/Error"

/me:

get:

summary: User Profile

description: The User Profile endpoint returns information about the Uber user that has authorized with the application.

tags:

- User

responses:

'200':

description: Profile information for a user

content:

application/json:

schema:

$ref: "#/components/schemas/Profile"

default:

description: Unexpected error

content:

application/json:

schema:

$ref: "#/components/schemas/Error"

/history:

get:

summary: User Activity

description: The User Activity endpoint returns data about a user's lifetime activity with Uber. The response will include pickup locations and times, dropoff locations and times, the distance of past requests, and information about which products were requested.
The history array in the response will have a maximum length based on the limit parameter. The response value count may exceed limit, therefore subsequent API requests may be necessary.

parameters:

- name: offset

in: query

schema:

type: integer

format: int32

description: Offset the list of returned results by this amount. Default is zero.

- name: limit

in: query

schema:

type: integer

format: int32

description: Number of items to retrieve. Default is 5, maximum is 100.

tags:

- User

responses:

'200':

description: History information for the given user

content:

application/json:

schema:

$ref: "#/components/schemas/Activities"

default:

description: Unexpected error

content:

application/json:

schema:

$ref: "#/components/schemas/Error"

components:

securitySchemes:

apikey:

type: apiKey

name: server_token

in: query

schemas:

Product:

properties:

product_id:

type: string

description: Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles.

description:

type: string

description: Description of product.

display_name:

type: string

description: Display name of product.

capacity:

type: integer

description: Capacity of product. For example, 4 people.

image:

type: string

description: Image URL representing the product.

ProductList:

properties:

products:

description: Contains the list of products

type: array

items:

$ref: "#/components/schemas/Product"

PriceEstimate:

properties:

product_id:

type: string

description: Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles

currency_code:

type: string

description: "[ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code."

display_name:

type: string

description: Display name of product.

estimate:

type: string

description: Formatted string of estimate in local currency of the start location. Estimate could be a range, a single number (flat rate) or "Metered" for TAXI.

low_estimate:

type: number

description: Lower bound of the estimated price.

high_estimate:

type: number

description: Upper bound of the estimated price.

surge_multiplier:

type: number

description: Expected surge multiplier. Surge is active if surge_multiplier is greater than 1. Price estimate already factors in the surge multiplier.

Profile:

properties:

first_name:

type: string

description: First name of the Uber user.

last_name:

type: string

description: Last name of the Uber user.

email:

type: string

description: Email address of the Uber user

picture:

type: string

description: Image URL of the Uber user.

promo_code:

type: string

description: Promo code of the Uber user.

Activity:

properties:

uuid:

type: string

description: Unique identifier for the activity

Activities:

properties:

offset:

type: integer

format: int32

description: Position in pagination.

limit:

type: integer

format: int32

description: Number of items to retrieve (100 max).

count:

type: integer

format: int32

description: Total number of items available.

history:

type: array

items:

$ref: "#/components/schemas/Activity"

Error:

properties:

code:

type: string

message:

type: string

fields:

type: string

这里将 OpenAPI 3.0 规范中把重点使用的 api 整理了一张思维导图(还不完善,会持续更新)

cdb41c9e52e2

OpenAPI 3.0.0.png

Swagger

Swagger 实际上包含了一系列的工具 Editor Codegen UI ...

Editor 用于使用 OpenAPI 编辑 yaml

Codegen 用于生成不同的 language library 的代码

UI 用于生成文档

下面介绍一下 Codegen 的使用:

确保装好了 maven

准备 swagger.yaml

编写 config.json 配置文件

因为之前提到 Swagger 可以生成各种 lang lib 的代码,所以这里便是进行此类配置:

查看配置 help

java -jar swagger-codegen-cli.jar config-help -l java

CONFIG OPTIONS

sortParamsByRequiredFlag

Sort method arguments to place required parameters before optional parameters. (Default: true)

ensureUniqueParams

Whether to ensure parameter names are unique in an operation (rename parameters that are not). (Default: true)

allowUnicodeIdentifiers

boolean, toggles whether unicode identifiers are allowed in names or not, default is false (Default: false)

modelPackage

package for generated models

apiPackage

package for generated api classes

invokerPackage

root package for generated code

groupId

groupId in generated pom.xml

artifactId

artifactId in generated pom.xml

artifactVersion

artifact version in generated pom.xml

artifactUrl

artifact URL in generated pom.xml

artifactDescription

artifact description in generated pom.xml

scmConnection

SCM connection in generated pom.xml

scmDeveloperConnection

SCM developer connection in generated pom.xml

scmUrl

SCM URL in generated pom.xml

developerName

developer name in generated pom.xml

developerEmail

developer email in generated pom.xml

developerOrganization

developer organization in generated pom.xml

developerOrganizationUrl

developer organization URL in generated pom.xml

licenseName

The name of the license

licenseUrl

The URL of the license

sourceFolder

source folder for generated code

localVariablePrefix

prefix for generated code members and local variables

serializableModel

boolean - toggle "implements Serializable" for generated models (Default: false)

bigDecimalAsString

Treat BigDecimal values as Strings to avoid precision loss. (Default: false)

fullJavaUtil

whether to use fully qualified name for classes under java.util. This option only works for Java API client (Default: false)

hideGenerationTimestamp

hides the timestamp when files were generated

withXml

whether to include support for application/xml content type. This option only works for Java API client (resttemplate) (Default: false)

dateLibrary

Option. Date library to use

joda - Joda (for legacy app only)

legacy - Legacy java.util.Date (if you really have a good reason not to use threetenbp

java8-localdatetime - Java 8 using LocalDateTime (for legacy app only)

java8 - Java 8 native JSR310 (preferred for jdk 1.8+) - note: this also sets "java8" to true

threetenbp - Backport of JSR310 (preferred for jdk < 1.8)

java8

Option. Use Java8 classes instead of third party equivalents

true - Use Java 8 classes such as Base64

false - Various third party libraries as needed

useRxJava

Whether to use the RxJava adapter with the retrofit2 library. (Default: false)

useRxJava2

Whether to use the RxJava2 adapter with the retrofit2 library. (Default: false)

parcelableModel

Whether to generate models for Android that implement Parcelable with the okhttp-gson library. (Default: false)

usePlay24WS

Use Play! 2.4 Async HTTP client (Play WS API) (Default: false)

supportJava6

Whether to support Java6 with the Jersey1 library. (Default: false)

useBeanValidation

Use BeanValidation API annotations (Default: false)

performBeanValidation

Perform BeanValidation (Default: false)

useGzipFeature

Send gzip-encoded requests (Default: false)

useRuntimeException

Use RuntimeException instead of Exception (Default: false)

library

library template (sub-template) to use (Default: okhttp-gson)

jersey1 - HTTP client: Jersey client 1.19.4. JSON processing: Jackson 2.8.9. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.

feign - HTTP client: OpenFeign 9.4.0. JSON processing: Jackson 2.8.9

jersey2 - HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.8.9

okhttp-gson - HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.8.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.

retrofit - HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.3.1 (Retrofit 1.9.0). IMPORTANT NOTE: retrofit1.x is no longer actively maintained so please upgrade to 'retrofit2' instead.

retrofit2 - HTTP client: OkHttp 3.8.0. JSON processing: Gson 2.6.1 (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2]=true'. (RxJava 1.x or 2.x)

resttemplate - HTTP client: Spring RestTemplate 4.3.9-RELEASE. JSON processing: Jackson 2.8.9

resteasy - HTTP client: Resteasy client 3.1.3.Final. JSON processing: Jackson 2.8.9

几个主要的配置参数:

library,生成的代码支付的类,有jersey1、jersey2、okhttp-gson、resttemplate、resteasy、feign、retrofit、retrofit2等几种类型,我们选择的retrofit2

developerName,开发者名字,会出现在代码文件里

developerEmail,开发者邮箱,会出现在代码文件里

developrOrganization,开发者组织,会出现在代码里

invokerPackage,项目的包名

apiPackage,生成的***Api.java文件的包名

modelPackage,生成的数据模型java文件包名

dateLibrary,时间使用的类开

useRxJava,是否使用rxjava生成api接口

useRxJava2,是否使用rxjava2的方式调用接口

generate 生成代码

首先打印参数信息

java -jar swagger-codegen-cli.jar generate help

NAME

swagger-codegen-cli generate - Generate code with chosen lang

SYNOPSIS

swagger-codegen-cli generate

[(-a | --auth )]

[--additional-properties ...]

[--api-package ] [--artifact-id ]

[--artifact-version ]

[(-c | --config )]

[-D ...] [--git-repo-id ]

[--git-user-id ] [--group-id ]

[--http-user-agent ]

(-i | --input-spec )

[--ignore-file-override ]

[--import-mappings ...]

[--instantiation-types ...]

[--invoker-package ]

(-l | --lang )

[--language-specific-primitives ...]

[--library ] [--model-name-prefix ]

[--model-name-suffix ]

[--model-package ]

[(-o | --output )]

[--release-note ] [--remove-operation-id-prefix]

[--reserved-words-mappings ...]

[(-s | --skip-overwrite)]

[(-t | --template-dir )]

[--type-mappings ...] [(-v | --verbose)]

OPTIONS

-a , --auth

adds authorization headers when fetching the swagger definitions

remotely. Pass in a URL-encoded string of name:header with a comma

separating multiple values

--additional-properties

sets additional properties that can be referenced by the mustache

templates in the format of name=value,name=value. You can also have

multiple occurrences of this option.

--api-package

package for generated api classes

--artifact-id

artifactId in generated pom.xml

--artifact-version

artifact version in generated pom.xml

-c , --config

Path to json configuration file. File content should be in a json

format {"optionKey":"optionValue", "optionKey1":"optionValue1"...}

Supported options can be different for each language. Run

config-help -l {lang} command for language specific config options.

-D

sets specified system properties in the format of

name=value,name=value (or multiple options, each with name=value)

--git-repo-id

Git repo ID, e.g. swagger-codegen.

--git-user-id

Git user ID, e.g. swagger-api.

--group-id

groupId in generated pom.xml

--http-user-agent

HTTP user agent, e.g. codegen_csharp_api_client, default to

'Swagger-Codegen/{packageVersion}}/{language}'

-i , --input-spec

location of the swagger spec, as URL or file (required)

--ignore-file-override

Specifies an override location for the .swagger-codegen-ignore file.

Most useful on initial generation.

--import-mappings

specifies mappings between a given class and the import that should

be used for that class in the format of type=import,type=import. You

can also have multiple occurrences of this option.

--instantiation-types

sets instantiation type mappings in the format of

type=instantiatedType,type=instantiatedType.For example (in Java):

array=ArrayList,map=HashMap. In other words array types will get

instantiated as ArrayList in generated code. You can also have

multiple occurrences of this option.

--invoker-package

root package for generated code

-l , --lang

client language to generate (maybe class name in classpath,

required)

--language-specific-primitives

specifies additional language specific primitive types in the format

of type1,type2,type3,type3. For example:

String,boolean,Boolean,Double. You can also have multiple

occurrences of this option.

--library

library template (sub-template)

--model-name-prefix

Prefix that will be prepended to all model names. Default is the

empty string.

--model-name-suffix

Suffix that will be appended to all model names. Default is the

empty string.

--model-package

package for generated models

-o , --output

where to write the generated files (current dir by default)

--release-note

Release note, default to 'Minor update'.

--remove-operation-id-prefix

Remove prefix of operationId, e.g. config_getId => getId

--reserved-words-mappings

specifies how a reserved name should be escaped to. Otherwise, the

default _ is used. For example id=identifier. You can also

have multiple occurrences of this option.

-s, --skip-overwrite

specifies if the existing files should be overwritten during the

generation.

-t , --template-dir

folder containing the template files

--type-mappings

sets mappings between swagger spec types and generated code types in

the format of swaggerType=generatedType,swaggerType=generatedType.

For example: array=List,map=Map,string=String. You can also have

multiple occurrences of this option.

-v, --verbose

verbose mode

几个主要参数:

-i 表示输入的文件,editor生成的设计文件路径,如:-i ~/Desktop/swagger.yaml

-o 代码生成目录,swagger codegen 把代码生成到什么地方,如:-o ~/Desktop

-l 生成代码语言,我们是生成java,如:-l java

-c 配置文件,配制文件路径,如:-c ~/Desktop/config.json

最后生成代码

java -jar swagger-codegen-cli.jar generate -i swagger.yaml -o client -l java -c config.json

成功在 ~/Desktop 下生成了相应的 code 和 doc

<think>好的,我现在需要处理用户关于Swagger YAML文件的说明和使用指南的请求。首先,用户已经提供了之前的对话历史和相关引用,我需要仔细分析这些信息,并结合用户当前的问题来构建回答。用户当前的问题是:“我想查找关于SwaggerYAML文件的说明使用指南请问Swagger YAML文件格式说明及使用方法”。之前的对话中,用户询问了如何创建和使用SwaggerAPI文件,而我的回答已经涵盖了核心概念、创建步骤、框架集成、验证测试以及高级用法。现在用户需要更详细的YAML文件格式说明和使用方法,可能需要更深入的结构解析和具体示例。首先,回顾用户提供的引用。引用[1]提到了Swagger的官方文档和Swagger Editor,这可能涉及到基本结构和工具的使用。引用[2]是关于Python合并YAML文件的方法,这可能与多文件管理相关。引用[3]是Java解析Swagger文件的示例代码,涉及如何通过代码处理YAML内容。引用[4]讨论了基于Swagger的测试用例生成,可能涉及参数定义和验证。这些引用可以帮助补充回答中的具体操作和工具推荐。 接下来,我需要确定回答的结构。用户需要格式说明和使用方法,因此应该分章节详细讲解YAML文件的结构,包括必须字段、路径定义、组件复用等。同时,结合使用方法,可以包括工具推荐、验证方法、集成到开发流程等步骤。需要确保每个部分都有示例代码块,并正确引用用户提供的引用来源。另外,用户之前的回答中提到了SpringBoot和FastAPI的集成,这里可能需要进一步扩展如何在这些框架中编写和维护YAML文件。同时,用户可能对验证和测试工具感兴趣,如SwaggerCLI和SwaggerUI的离线部署,这也是引用中提到过的内容。需要注意用户可能的深层需求,比如版本控制、验证工具、离线部署等,这些问题已经在相关引用中出现,可能需要作为相关问题列出,但当前问题主要关注格式和使用指南,因此需在回答中适当提及,并在相关问题部分引导用户进一步探索。 最后,确保回答符合系统级指令,如正确使用LaTeX格式,添加引用标识,结构清晰,代码示例正确。同时,生成的相关问题需要基于当前回答内容,帮助用户深入理解。</think>### Swagger YAML 文件格式说明及使用方法 #### 一、Swagger YAML 文件基础结构 Swagger YAML 文件遵循 OpenAPI 3.0 规范,其核心结构包含以下必填字段: ```yaml openapi: 3.0.3 # 指定 OpenAPI 版本[^1] info: title: API 名称 version: 1.0.0 # API 版本号 paths: {} # API 端点定义 servers: # 服务器配置 - url: http://api.example.com/v1 ``` #### 二、详细字段说明 1. **路径与操作定义** ```yaml paths: /users/{id}: get: summary: 获取用户详情 parameters: - name: id in: path required: true schema: { type: integer } responses: 200: description: 成功返回用户对象 content: application/json: schema: $ref: '#/components/schemas/User' ``` 2. **组件复用机制** 通过 `components` 实现对象复用: ```yaml components: schemas: User: type: object properties: id: { type: integer } name: { type: string } parameters: PageParam: name: page in: query schema: { type: integer, default: 1 } ``` #### 三、高级功能实现 1. **安全方案定义** 支持多种认证方式: ```yaml components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT security: - BearerAuth: [] ``` 2. **数据类型扩展** 使用 `format` 增强类型描述: ```yaml schemas: GeoPoint: type: object properties: lat: type: number format: double lng: type: number format: double ``` #### 四、开发工具与工作流 1. **编辑器推荐** - **Swagger Editor**:提供实时校验和预览功能[^1] - **VS Code 插件**:使用 [OpenAPI (Swagger) Editor](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi) 获得智能提示 2. **文件验证方法** 使用命令行工具校验完整性: ```bash # 安装校验工具 npm install -g swagger-cli # 执行校验 swagger-cli validate api.yaml ``` 3. **多文件管理** Python 实现文件合并示例[^2]: ```python import yaml def merge_yaml(files): merged = {} for f in files: with open(f) as stream: merged.update(yaml.safe_load(stream)) return merged ``` #### 五、框架集成示例 1. **Java 解析示例** 使用 Swagger Parser 解析 YAML 文件[^3]: ```java SwaggerParseResult result = new OpenAPIParser().readLocation("api.yaml", null, null); OpenAPI openAPI = result.getOpenAPI(); List<PathItem> paths = openAPI.getPaths().values().stream().collect(Collectors.toList()); ``` 2. **自动生成测试用例** 基于参数定义生成异常测试场景[^4]: ```yaml /products: post: parameters: - name: price in: body schema: type: number minimum: 0 exclusiveMaximum: 10000 ``` 可自动生成 `price=-1`, `price=10000` 等非法值用例。 --- ### 使用建议 1. **版本控制策略** - 在 `info.version` 字段维护 API 版本 - 使用 Git 管理 YAML 文件变更历史 2. **文档生成流程** ```mermaid graph TD A[编写YAML] --> B[校验语法] B --> C[生成代码] C --> D[部署Swagger UI] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值