Skip to content

MillerTechnologyPeru/OpenAPIKit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MIT license Swift 5.1 Build Status

OpenAPIKit

A library containing Swift types that encode to- and decode from OpenAPI Documents and their components.

Usage

Decoding OpenAPI Documents

You can decode a JSON OpenAPI document (i.e. using the JSONDecoder from Foundation library) or a YAML OpenAPI document (i.e. using the YAMLDecoder from the Yams library) with the following code:

let decoder = ... // JSONDecoder() or YAMLDecoder()
let openAPIDoc = try decoder.decode(OpenAPI.Document, from: ...)

Decoding Errors

You can wrap any error you get back from a decoder in OpenAPI.Error to get a friendlier human-readable description from localizedDescription.

do {
  try decoder.docode(OpenAPI.Document, from: ...)
} catch let error {
  print(OpenAPI.Error(from: error).localizedDescription)  
}

Encoding OpenAPI Documents

You can encode a JSON OpenAPI document (i.e. using the JSONEncoder from the Foundation library) or a YAML OpenAPI document (i.e. using the YAMLEncoder from the Yams library) with the following code:

let openAPIDoc = ...
let encoder = ... // JSONEncoder() or YAMLEncoder()
let encodedOpenAPIDoc = try encoder.encode(openAPIDoc)

A note on dictionary ordering

The Foundation library's JSONEncoder and JSONDecoder do not make any guarantees about the ordering of keyed containers. This means decoding a JSON OpenAPI Document and then encoding again might result in the document's various hashed structures being in a totally different order.

If retaining order is important for your use-case, I recommend the Yams and FineJSON libraries for YAML and JSON respectively.

Generating OpenAPI Documents

See VaporOpenAPI / VaporOpenAPIExample for an example of generating OpenAPI from a Vapor application's routes.

See JSONAPI+OpenAPI for an example of generating OpenAPI response schemas from JSON:API response documents.

OpenAPI Document structure

The types used by this library largely mirror the object definitions found in the OpenAPI specification version 3.0.2. The Project Status lists each object defined by the spec and the name of the respective type in this library.

Document Root

At the root there is an OpenAPI.Document. In addition to some information that applies to the entire API, the document contains OpenAPI.Components (essentially a dictionary of reusable components that can be referenced with JSONReferences) and an OpenAPI.PathItem.Map (a dictionary of routes your API defines).

Routes

Each route is an entry in the document's OpenAPI.PathItem.Map. The keys of this dictionary are the paths for each route (i.e. /widgets). The values of this dictionary are OpenAPI.PathItems which define any combination of endpoints (i.e. GET, POST, PATCH, etc.) that the given route supports.

Endpoints

Each endpoint on a route is defined by an OpenAPI.PathItem.Operation. Among other things, this operation can specify the parameters (path, query, header, etc.), request body, and response bodies/codes supported by the given endpoint.

Request/Response Bodies

Request and response bodies can be defined in great detail using OpenAPI's derivative of the JSON Schema specification. This library uses the JSONSchema type for such schema definitions.

Schemas

Fundamental types are specified as JSONSchema.integer, JSONSchema.string, JSONSchema.boolean, etc.

Properties are given as arguments to static constructors. By default, types are non-nullable, required, and generic.

A type can be made optional (i.e. it can be omitted) with JSONSchema.integer(required: false) or JSONSchema.integer.optionalSchemaObject(). A type can be made nullable with JSONSchema.number(nullable: true) or JSONSchema.number.nullableSchemaObject().

A type's format can be further specified, for example JSONSchema.number(format: .double) or JSONSchema.string(format: .dateTime).

You can specify a schema's allowed values (e.g. for an enumerated type) with JSONSchema.string(allowedValues: "hello", "world").

Each type has its own additional set of properties that can be specified. For example, integers can have a minimum value: JSONSchema.integer(minimum: (0, exclusive: true)) (where exclusive means the number must be greater than 0, not greater-than-or-equal-to 0).

Compound objects can be built with JSONSchema.array, JSONSchema.object, JSONSchema.all(of:), etc.

For example, perhaps a person is represented by the schema:

JSONSchema.object(
  title: "Person",
  properties: [
    "first_name": .string(minLength: 2),
    "last_name": .string(nullable: true),
    "age": .integer,
    "favorite_color": .string(allowedValues: "red", "green", "blue")
  ]
)
Generating Schemas from Swift Types

Some schemas can be easily generated from Swift types. Many of the fundamental Swift types support schema representations out-of-box.

For example, the following are true

String.openAPINode() == JSONSchema.string

Bool.openAPINode() == JSONSchema.boolean

Double.openAPINode() == JSONSchema.number(format: .double)

Float.openAPINode() == JSONSchema.number(format: .float)
...

Array and Optional are supported out-of-box. For example, the following are true

[String].openAPINode() == .array(items: .string)

[Int].openAPINode() == .array(items: .integer)

Int32?.openAPINode() == .integer(format: .int32, required: false)

[String?].openAPINode() == .array(items: .string(required: false))
...

Additional schema generation support can be found in the mattpolzin/OpenAPIReflection library.

Notes

This library does not currently support file reading at all muchless following $refs to other files and loading them in.

This library is opinionated about a few defaults when you use the Swift types, however encoding and decoding stays true to the spec. Some key things to note:

  1. Within schemas, required is specified on the property rather than being specified on the parent object (encoding/decoding still follows the OpenAPI spec).
    • ex JSONSchema.object(properties: [ "val": .string(required: true)]) is an "object" type with a required "string" type property.
  2. Within schemas, required defaults to true on initialization (again, encoding/decoding still follows the OpenAPI spec).
    • ex. JSONSchema.string is a required "string" type.
    • ex. JSONSchema.string(required: false) is an optional "string" type.

See A note on dictionary ordering before deciding on an encoder/decoder to use with this library.

Project Status

OpenAPI Object (OpenAPI.Document)

  • openapi (openAPIVersion)
  • info
  • servers
  • paths
  • components
  • security
  • tags
  • externalDocs
  • specification extensions

Info Object (OpenAPI.Document.Info)

  • title
  • description
  • termsOfService
  • contact
  • license
  • version
  • specification extensions

Contact Object (OpenAPI.Document.Info.Contact)

  • name
  • url
  • email
  • specification extensions

License Object (OpenAPI.Document.Info.License)

  • name
  • url
  • specification extensions

Server Object (OpenAPI.Server)

  • url
  • description
  • variables
  • specification extensions

Server Variable Object (OpenAPI.Server.Variable)

  • enum
  • default
  • description
  • specification extensions

Components Object (OpenAPI.Components)

  • schemas
  • responses
  • parameters
  • examples
  • requestBodies
  • headers
  • securitySchemes
  • links
  • callbacks
  • specification extensions

Paths Object (OpenAPI.PathItem.Map)

  • dictionary
  • [ ] specification extensions (not a planned addition)

Path Item Object (OpenAPI.PathItem)

  • summary
  • description
  • servers
  • parameters
  • get
  • put
  • post
  • delete
  • options
  • head
  • patch
  • trace
  • specification extensions

Operation Object (OpenAPI.PathItem.Operation)

  • tags
  • summary
  • description
  • externalDocs
  • operationId
  • parameters
  • requestBody
  • responses
  • callbacks
  • deprecated
  • security
  • servers
  • specification extensions

External Document Object (OpenAPI.ExternalDoc)

  • description
  • url
  • specification extensions

Parameter Object (OpenAPI.PathItem.Parameter)

  • name
  • in (parameterLocation)
  • description
  • required (part of parameterLocation)
  • deprecated
  • allowEmptyValue (part of parameterLocation)
  • content (schemaOrContent)
  • schema (schemaOrContent)
    • style
    • explode
    • allowReserved
    • example
    • examples
  • specification extensions

Request Body Object (OpenAPI.Request)

  • description
  • content
  • required
  • specification extensions

Media Type Object (OpenAPI.Content)

  • schema
  • example
  • examples
  • encoding
  • specification extensions (vendorExtensions)

Encoding Object (OpenAPI.Content.Encoding)

  • contentType
  • headers
  • style
  • explode
  • allowReserved
  • specification extensions

Responses Object (OpenAPI.Response.Map)

  • dictionary
  • [ ] specification extensions (not a planned addition)

Response Object (OpenAPI.Response)

  • description
  • headers
  • content
  • links
  • specification extensions

Callback Object

  • {expression}
  • specification extensions

Example Object (OpenAPI.Example)

  • summary
  • description
  • value
  • externalValue (part of value)
  • specification extensions (vendorExtensions)

Link Object

  • operationRef
  • operationId
  • parameters
  • requestBody
  • description
  • server
  • specification extensions

Header Object (OpenAPI.Header)

  • description
  • required
  • deprecated
  • content
  • schema
    • style
    • explode
    • allowReserved
    • example
    • examples
  • specification extensions

Tag Object (OpenAPI.Tag)

  • name
  • description
  • externalDocs
  • specification extensions

Reference Object (JSONReference)

  • $ref
    • local (same file) reference (node case)
      • encode
      • decode
      • dereference
    • remote (different file) reference (file case)
      • encode
      • decode
      • dereference

Schema Object (JSONSchema)

  • Mostly complete support for JSON Schema inherited keywords
  • nullable
  • discriminator
  • readOnly (permissions .readOnly case)
  • writeOnly (permissions .writeOnly case)
  • xml
  • externalDocs
  • example
  • deprecated
  • specification extensions

Discriminator Object (OpenAPI.Discriminator)

  • propertyName
  • mapping

XML Object (OpenAPI.XML)

  • name
  • namespace
  • prefix
  • attribute
  • wrapped
  • specification extensions

Security Scheme Object (OpenAPI.SecurityScheme)

  • type
  • description
  • name (SecurityType .apiKey case)
  • in (location in SecurityType .apiKey case)
  • scheme (SecurityType .http case)
  • bearerFormat (SecurityType .http case)
  • flows (SecurityType .oauth2 case)
  • openIdConnectUrl (SecurityType .openIdConnect case)
  • specification extensions

OAuth Flows Object (OpenAPI.OauthFlows)

  • implicit
  • password
  • clientCredentials
  • authorizationCode
  • specification extensions

OAuth Flow Object (OpenAPI.OauthFlows.*)

  • OpenAPI.OauthFlows.Implicit
  • OpenAPI.OauthFlows.Password
  • OpenAPI.OauthFlows.ClientCredentials
  • OpenAPI.OauthFlows.AuthorizationCode
  • authorizationUrl
  • tokenUrl
  • refreshUrl
  • scopes
  • specification extensions

Security Requirement Object (OpenAPI.Document.SecurityRequirement)

  • {name} (using JSONReferences instead of a stringy API)

About

Codable Swift OpenAPI implementation.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 100.0%