SwiftOpenAPI

build Version License Platform

描述

SwiftOpenAPI 是一个 Swift 库,可以生成与 OpenAPI 3.1.0 版本兼容的输出。您可以使用 OpenAPIObject 类型描述您的 API。
该库的主要重点是简化语法:积极使用字面量(数组、字典、字符串等)和静态方法大大简化了在 Swift 中编写和阅读 OpenAPI 文档的过程。

简短示例

try OpenAPIObject(
    openapi: "3.0.11",
    info: InfoObject(
        title: "Example API",
        version: "0.1.0"
    ),
    servers: [
        "https://example-server.com",
        "https://example-server-test.com"
    ],
    paths: [
        "services": .get(
            summary: "Get services",
            OperationObject(description: "Get services")
        ),
        "login": .post(
            OperationObject(
                description: "login",
                requestBody: .ref(components: \.requestBodies, "LoginRequest"),
                responses: [
                    .ok: .ref(components: \.responses, "LoginResponse"),
                    .unauthorized: .ref(components: \.responses, "ErrorResponse")
                ]
            )
        ),
        "/services/{serviceID}": [
            .get: OperationObject(description: "Get service"),
            .delete: OperationObject(description: "Delete service")
        ],
        "/services": .ref(components: \.pathItems, "T")
    ],
    components: ComponentsObject(
        schemas: [
            "LoginBody": [
                "username": .string,
                "password": .string
            ],
            "LoginResponse": .value(.encode(LoginResponse.example))
        ],
        examples: [
            "LoginBody": [
                "username": "SomeUser",
                "password": "12345678"
            ],
            "LoginResponse": .value(
            	ExampleObject(value: .encode(LoginResponse.example))
            )
        ],
        requestBodies: [
            "LoginRequest": .value(
                RequestBodyObject(
                    content: [
                        .application(.json): MediaTypeObject(
                            schema: .ref(components: \.schemas, "LoginBody")
                        )
                    ],
                    required: nil
                )
            )
        ]
    )
)

宠物商店示例

PetsSwagger.swift 很好地展示了语法

Codable 类型创建 schemas 和 parameters

可以从 Codable 类型创建 SchemeObject[ParameterObject]AnyValue[String: HeaderObject] 实例。可以使用 SchemeObject.decode/encode[ParameterObject].decode/encode[String: HeaderObject].decode/encodeAnyValue.encode 方法来实现。

let loginBodySchemeFromType: SchemeObject = try .decode(LoginBody.self)
let loginBodySchemeFromInstance: SchemeObject = try .encode(LoginBody.example)
let loginBodyExample = try ExampleObject(value: .encode(LoginBody.example))

您可以通过实现 OpenAPIDescriptableOpenAPIType 协议来自定义编码/解码结果。

  1. OpenAPIDescriptable 协议允许您为类型及其属性提供自定义描述。@OpenAPIAutoDescriptable 宏使用您的注释来实现此协议。
import SwiftOpenAPI

@OpenAPIDescriptable
/// Login request body.
struct LoginBody: Codable {
    
    /// Username string.
    let username: String
    /// Password string. Encoded.
    let password: String
}

手动方式

struct LoginBody: Codable, OpenAPIDescriptable {
    
    let username: String
    let password: String
    
    static var openAPIDescription: OpenAPIDescriptionType? {
        OpenAPIDescription<CodingKeys>("Login request body.")
            .add(for: .username, "Username string.")
            .add(for: .password, "Password string. Encoded.")
    }
}
  1. OpenAPIType 协议允许您为类型提供自定义 schema。
struct Color: Codable, OpenAPIType {
    
    static var openAPISchema: SchemaObject {
        .string(format: "hex", description: "Color in hex format")
    }
}

规范扩展

虽然 OpenAPI 规范试图适应大多数用例,但可以添加 额外数据 以在特定点扩展规范。

var api = OpenAPIObject(...)
api.specificationExtensions = ["x-some-extension": "some value"]
// or
api.specificationExtensions = try? SpecificationExtensions(from: someEncodable)

为任何可编码结构实现额外的动态属性是一项有点棘手的挑战。解决方案是将 SpecificationExtendable 协议与 WithSpecExtensions 属性包装器结合使用。 有两种方法可以使用附加属性解码/编码 SpecificationExtendable 类型

  1. 使用 SpecificationExtendable.json, SpecificationExtendable.Type.from(json:) 方法。
let schema = try SchemaObject.from(json: jsonData)
let jsonData = try schema.json()
  1. 如果您不能使用自定义解码方法,您可以使用 WithSpecExtensions 包装器。
let api = try WithSpecExtensions(wrappedValue: OpenAPIObject(...))
let jsonData = try JSONEncoder().encode(api)

待办事项

安装

  1. Swift 包管理器

创建一个 Package.swift 文件。

// swift-tools-version:5.9
import PackageDescription

let package = Package(
  name: "SomeProject",
  dependencies: [
    .package(url: "https://github.com/dankinsoid/SwiftOpenAPI.git", from: "2.20.0")
  ],
  targets: [
    .target(name: "SomeProject", dependencies: ["SwiftOpenAPI"])
  ]
)
$ swift build

相关项目

作者

dankinsoid, voidilov@gmail.com

许可证

SwiftOpenAPI 在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。