Convert Figma logo to code with AI

getkin logokin-openapi

OpenAPI 3.0 (and Swagger v2) implementation for Go (parsing, converting, validation, and more)

2,546
426
2,546
102

Top Related Projects

The OpenAPI Specification Repository

Examples and server integrations for generating the Swagger API Specification, which enables easy access to your REST API

GUI / visual editor for creating and editing OpenAPI / Swagger definitions

Swagger 2.0 and OpenAPI 3.0 parser/validator

A flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI v3.1, v3.0, and v2.0 as well as AsyncAPI v2.x.

Quick Overview

The getkin/kin-openapi repository is a Go package for handling OpenAPI (formerly known as Swagger) specifications. It provides tools for parsing, validating, and working with OpenAPI 3.0 and 3.1 documents, making it easier for developers to integrate OpenAPI functionality into their Go applications.

Pros

  • Supports both OpenAPI 3.0 and 3.1 specifications
  • Provides robust parsing and validation capabilities
  • Offers a comprehensive set of tools for working with OpenAPI documents
  • Actively maintained with regular updates and improvements

Cons

  • Limited to Go language, not suitable for other programming environments
  • May have a steeper learning curve for developers new to OpenAPI concepts
  • Documentation could be more extensive, especially for advanced use cases
  • Some users report occasional issues with complex OpenAPI specifications

Code Examples

  1. Parsing an OpenAPI document:
import (
    "github.com/getkin/kin-openapi/openapi3"
)

loader := openapi3.NewLoader()
doc, err := loader.LoadFromFile("path/to/openapi.yaml")
if err != nil {
    // Handle error
}
  1. Validating an OpenAPI document:
err = doc.Validate(context.Background())
if err != nil {
    // Handle validation error
}
  1. Accessing OpenAPI components:
schema := doc.Components.Schemas["User"]
path := doc.Paths["/users"]
operation := path.Get
  1. Serializing an OpenAPI document:
import (
    "encoding/json"
)

jsonData, err := json.Marshal(doc)
if err != nil {
    // Handle error
}

Getting Started

To use kin-openapi in your Go project, follow these steps:

  1. Install the package:

    go get github.com/getkin/kin-openapi
    
  2. Import the required modules in your Go code:

    import (
        "github.com/getkin/kin-openapi/openapi3"
        "github.com/getkin/kin-openapi/routers"
    )
    
  3. Start using the package to work with OpenAPI documents, as shown in the code examples above.

Competitor Comparisons

The OpenAPI Specification Repository

Pros of OpenAPI-Specification

  • Official specification repository, providing the authoritative source for OpenAPI standards
  • Extensive documentation and examples for implementing OpenAPI in various scenarios
  • Large community support and regular updates to the specification

Cons of OpenAPI-Specification

  • Focuses on the specification itself, not providing implementation tools or libraries
  • May require additional resources for practical implementation in projects

Code Comparison

OpenAPI-Specification (YAML example):

openapi: 3.0.0
info:
  title: Sample API
  version: 1.0.0
paths:
  /users:
    get:
      summary: Returns a list of users

kin-openapi (Go example):

swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromFile("openapi.yaml")
if err != nil {
    panic(err)
}

Summary

OpenAPI-Specification is the official repository for the OpenAPI standard, offering comprehensive documentation and examples. It's ideal for understanding the specification but doesn't provide implementation tools. kin-openapi, on the other hand, is a Go library that offers practical tools for working with OpenAPI specifications, including parsing, validation, and manipulation of OpenAPI documents. While OpenAPI-Specification is essential for staying up-to-date with the standard, kin-openapi provides a more hands-on approach for developers working with OpenAPI in Go projects.

Examples and server integrations for generating the Swagger API Specification, which enables easy access to your REST API

Pros of swagger-core

  • More comprehensive ecosystem with additional tools and integrations
  • Stronger community support and wider adoption in enterprise environments
  • Better documentation and extensive examples for various use cases

Cons of swagger-core

  • Heavier and more complex, potentially overkill for smaller projects
  • Steeper learning curve, especially for developers new to OpenAPI/Swagger
  • Less flexible for custom extensions and modifications

Code Comparison

swagger-core:

@Path("/users")
@Api(value = "/users", description = "User management")
public class UserResource {
    @GET
    @ApiOperation(value = "Get all users", response = User.class, responseContainer = "List")
    public Response getUsers() {
        // Implementation
    }
}

kin-openapi:

func main() {
    swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromFile("openapi.yaml")
    if err != nil {
        panic(err)
    }
    // Use the loaded OpenAPI specification
}

Summary

swagger-core offers a more robust ecosystem and better support for large-scale projects, while kin-openapi provides a lightweight and flexible alternative for Go developers. The choice between the two depends on project requirements, team expertise, and the desired level of customization.

GUI / visual editor for creating and editing OpenAPI / Swagger definitions

Pros of openapi-gui

  • User-friendly graphical interface for creating and editing OpenAPI specifications
  • Web-based tool, accessible from any browser without installation
  • Supports real-time preview and validation of the OpenAPI document

Cons of openapi-gui

  • Limited to OpenAPI v3.0 specifications, while kin-openapi supports multiple versions
  • Less extensive validation and parsing capabilities compared to kin-openapi
  • Not suitable for programmatic manipulation of OpenAPI documents

Code Comparison

kin-openapi (Go):

swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromFile("openapi.yaml")
if err != nil {
    log.Fatal(err)
}

openapi-gui (JavaScript):

fetch('openapi.yaml')
  .then(response => response.text())
  .then(yaml => {
    editor.setValue(yaml);
  });

Summary

openapi-gui is a web-based GUI tool for creating and editing OpenAPI specifications, offering a user-friendly interface and real-time preview. However, it has limitations in terms of version support and advanced functionality. kin-openapi, on the other hand, is a Go library for parsing and validating OpenAPI documents, providing more extensive capabilities for programmatic manipulation but lacking a graphical interface. The choice between the two depends on the specific use case and development requirements.

Swagger 2.0 and OpenAPI 3.0 parser/validator

Pros of swagger-parser

  • More comprehensive parsing and validation capabilities for OpenAPI/Swagger specifications
  • Supports both synchronous and asynchronous parsing methods
  • Extensive documentation and examples available

Cons of swagger-parser

  • Larger package size and potentially higher memory usage
  • May have slower performance for simple parsing tasks
  • Less frequent updates and maintenance compared to kin-openapi

Code Comparison

swagger-parser:

const SwaggerParser = require("swagger-parser");

SwaggerParser.validate("api.yaml", (err, api) => {
  if (err) {
    console.error(err);
  } else {
    console.log("API name: %s, Version: %s", api.info.title, api.info.version);
  }
});

kin-openapi:

import "github.com/getkin/kin-openapi/openapi3"

loader := openapi3.NewLoader()
doc, err := loader.LoadFromFile("api.yaml")
if err != nil {
    panic(err)
}
fmt.Printf("API name: %s, Version: %s\n", doc.Info.Title, doc.Info.Version)

Both libraries offer parsing and validation capabilities for OpenAPI/Swagger specifications. swagger-parser provides more comprehensive features and supports both sync and async methods, but may have higher resource usage. kin-openapi is lighter and potentially faster for simple tasks, with more frequent updates. The choice depends on specific project requirements and language preferences.

A flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI v3.1, v3.0, and v2.0 as well as AsyncAPI v2.x.

Pros of Spectral

  • More flexible and customizable linting rules
  • Supports multiple API description formats (OpenAPI, AsyncAPI, JSON Schema)
  • Extensive documentation and community support

Cons of Spectral

  • Steeper learning curve for complex custom rules
  • May require more setup time for advanced configurations

Code Comparison

Spectral rule definition:

rules:
  operation-description:
    description: Operation must have a description.
    given: $.paths[*][*]
    then:
      field: description
      function: truthy

kin-openapi validation:

swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromFile("openapi.yaml")
if err != nil {
    fmt.Println("Error:", err)
}

Key Differences

  • Spectral focuses on linting and customizable rules, while kin-openapi is more oriented towards parsing and validation
  • Spectral offers a CLI tool for easy integration, whereas kin-openapi is primarily used as a library
  • kin-openapi provides stronger typing and Go-specific features, while Spectral is more language-agnostic

Use Cases

  • Choose Spectral for flexible linting and rule customization across multiple API formats
  • Opt for kin-openapi when working with Go projects and requiring strong typing for OpenAPI specifications

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

CI Go Report Card GoDoc Join Gitter Chat Channel -

Introduction

A Go project for handling OpenAPI files. We target:

Licensed under the MIT License.

Contributors, users and sponsors

The project has received pull requests from many people. Thanks to everyone!

Please, give back to this project by becoming a sponsor.

Here's some projects that depend on kin-openapi:

Alternatives

Be sure to check OpenAPI Initiative's great tooling list as well as OpenAPI.Tools.

Structure

  • openapi2 (godoc)
    • Support for OpenAPI 2 files, including serialization, deserialization, and validation.
  • openapi2conv (godoc)
    • Converts OpenAPI 2 files into OpenAPI 3 files.
  • openapi3 (godoc)
    • Support for OpenAPI 3 files, including serialization, deserialization, and validation.
  • openapi3filter (godoc)
    • Validates HTTP requests and responses
    • Provides a gorilla/mux router for OpenAPI operations
  • openapi3gen (godoc)
    • Generates *openapi3.Schema values for Go types.

Some recipes

Validating an OpenAPI document

go run github.com/getkin/kin-openapi/cmd/validate@latest [--circular] [--defaults] [--examples] [--ext] [--patterns] -- <local YAML or JSON file>

Loading OpenAPI document

Use openapi3.Loader, which resolves all references:

loader := openapi3.NewLoader()
doc, err := loader.LoadFromFile("my-openapi-spec.json")

Getting OpenAPI operation that matches request

loader := openapi3.NewLoader()
doc, _ := loader.LoadFromData([]byte(`...`))
_ = doc.Validate(loader.Context)
router, _ := gorillamux.NewRouter(doc)
route, pathParams, _ := router.FindRoute(httpRequest)
// Do something with route.Operation

Validating HTTP requests/responses

package main

import (
	"context"
	"fmt"
	"net/http"

	"github.com/getkin/kin-openapi/openapi3"
	"github.com/getkin/kin-openapi/openapi3filter"
	"github.com/getkin/kin-openapi/routers/gorillamux"
)

func main() {
	ctx := context.Background()
	loader := &openapi3.Loader{Context: ctx, IsExternalRefsAllowed: true}
	doc, _ := loader.LoadFromFile(".../My-OpenAPIv3-API.yml")
	// Validate document
	_ = doc.Validate(ctx)
	router, _ := gorillamux.NewRouter(doc)
	httpReq, _ := http.NewRequest(http.MethodGet, "/items", nil)

	// Find route
	route, pathParams, _ := router.FindRoute(httpReq)

	// Validate request
	requestValidationInput := &openapi3filter.RequestValidationInput{
		Request:    httpReq,
		PathParams: pathParams,
		Route:      route,
	}
	_ = openapi3filter.ValidateRequest(ctx, requestValidationInput)

	// Handle that request
	// --> YOUR CODE GOES HERE <--
	responseHeaders := http.Header{"Content-Type": []string{"application/json"}}
	responseCode := 200
	responseBody := []byte(`{}`)

	// Validate response
	responseValidationInput := &openapi3filter.ResponseValidationInput{
		RequestValidationInput: requestValidationInput,
		Status:                 responseCode,
		Header:                 responseHeaders,
	}
	responseValidationInput.SetBodyBytes(responseBody)
	_ = openapi3filter.ValidateResponse(ctx, responseValidationInput)
}

Custom content type for body of HTTP request/response

By default, the library parses a body of the HTTP request and response if it has one of the following content types: "text/plain" or "application/json". To support other content types you must register decoders for them:

func main() {
	// ...

	// Register a body's decoder for content type "application/xml".
	openapi3filter.RegisterBodyDecoder("application/xml", xmlBodyDecoder)

	// Now you can validate HTTP request that contains a body with content type "application/xml".
	requestValidationInput := &openapi3filter.RequestValidationInput{
		Request:    httpReq,
		PathParams: pathParams,
		Route:      route,
	}
	if err := openapi3filter.ValidateRequest(ctx, requestValidationInput); err != nil {
		panic(err)
	}

	// ...

	// And you can validate HTTP response that contains a body with content type "application/xml".
	if err := openapi3filter.ValidateResponse(ctx, responseValidationInput); err != nil {
		panic(err)
	}
}

func xmlBodyDecoder(body io.Reader, h http.Header, schema *openapi3.SchemaRef, encFn openapi3filter.EncodingFn) (decoded any, err error) {
	// Decode body to a primitive, []any, or map[string]any.
}

Custom function to check uniqueness of array items

By default, the library checks unique items using the following predefined function:

func isSliceOfUniqueItems(xs []any) bool {
	s := len(xs)
	m := make(map[string]struct{}, s)
	for _, x := range xs {
		key, _ := json.Marshal(&x)
		m[string(key)] = struct{}{}
	}
	return s == len(m)
}

In the predefined function json.Marshal is used to generate a string that can be used as a map key which is to check the uniqueness of an array when the array items are objects or arrays. You can register you own function according to your input data to get better performance:

func main() {
	// ...

	// Register a customized function used to check uniqueness of array.
	openapi3.RegisterArrayUniqueItemsChecker(arrayUniqueItemsChecker)

	// ... other validate codes
}

func arrayUniqueItemsChecker(items []any) bool {
	// Check the uniqueness of the input slice
}

Custom function to change schema error messages

By default, the error message returned when validating a value includes the error reason, the schema, and the input value.

For example, given the following schema:

{
  "type": "string",
  "allOf": [
    { "pattern": "[A-Z]" },
    { "pattern": "[a-z]" },
    { "pattern": "[0-9]" },
    { "pattern": "[!@#$%^&*()_+=-?~]" }
  ]
}

Passing the input value "secret" to this schema will produce the following error message:

string doesn't match the regular expression "[A-Z]"
Schema:
  {
    "pattern": "[A-Z]"
  }

Value:
  "secret"

Including the original value in the error message can be helpful for debugging, but it may not be appropriate for sensitive information such as secrets.

To disable the extra details in the schema error message, you can set the openapi3.SchemaErrorDetailsDisabled option to true:

func main() {
	// ...

	// Disable schema error detailed error messages
	openapi3.SchemaErrorDetailsDisabled = true

	// ... other validate codes
}

This will shorten the error message to present only the reason:

string doesn't match the regular expression "[A-Z]"

For more fine-grained control over the error message, you can pass a custom openapi3filter.Options object to openapi3filter.RequestValidationInput that includes a openapi3filter.CustomSchemaErrorFunc.

func validationOptions() *openapi3filter.Options {
	options := &openapi3filter.Options{}
	options.WithCustomSchemaErrorFunc(safeErrorMessage)
	return options
}

func safeErrorMessage(err *openapi3.SchemaError) string {
	return err.Reason
}

This will change the schema validation errors to return only the Reason field, which is guaranteed to not include the original value.

Reconciling component $ref types

ReferencesComponentInRootDocument is a useful helper function to check if a component reference coincides with a reference in the root document's component objects fixed fields.

This can be used to determine if two schema definitions are of the same structure, helpful for code generation tools when generating go type models.

doc, err = loader.LoadFromFile("openapi.yml")

for _, path := range doc.Paths.InMatchingOrder() {
	pathItem := doc.Paths.Find(path)

	if pathItem.Get == nil || pathItem.Get.Responses.Status(200) {
		continue
	}

	for _, s := range pathItem.Get.Responses.Status(200).Value.Content {
		name, match := ReferencesComponentInRootDocument(doc, s.Schema)
		fmt.Println(path, match, name) // /record true #/components/schemas/BookRecord
	}
}

CHANGELOG: Sub-v1 breaking API changes

v0.127.0

  • Downgraded github.com/gorilla/mux dep from 1.8.1 to 1.8.0.

v0.126.0

  • openapi3.CircularReferenceError and openapi3.CircularReferenceCounter are removed. openapi3.Loader now implements reference backtracking, so any kind of circular references should be properly resolved.
  • InternalizeRefs now takes a refNameResolver that has access to openapi3.T and more properties of the reference needing resolving.
  • The DefaultRefNameResolver has been updated, choosing names that will be less likely to collide with each other. Because of this internalized specs will likely change slightly.
  • openapi3.Format and openapi3.FormatCallback are removed and the type of openapi3.SchemaStringFormats has changed.

v0.125.0

  • The openapi3filter.ErrFunc and openapi3filter.LogFunc func types now take the validated request's context as first argument.

v0.124.0

  • openapi3.Schema.Type & openapi2.Parameter.Type fields went from a string to the type *Type with methods: Includes, Is, Permits & Slice.

v0.122.0

  • Paths field of openapi3.T is now a pointer
  • Responses field of openapi3.Operation is now a pointer
  • openapi3.Paths went from map[string]*PathItem to a struct with an Extensions field and methods: Set, Value, Len, Map, and New*.
  • openapi3.Callback went from map[string]*PathItem to a struct with an Extensions field and methods: Set, Value, Len, Map, and New*.
  • openapi3.Responses went from map[string]*ResponseRef to a struct with an Extensions field and methods: Set, Value, Len, Map, and New*.
  • (openapi3.Responses).Get(int) renamed to (*openapi3.Responses).Status(int)

v0.121.0

  • Introduce openapi3.RequestBodies (an alias on map[string]*openapi3.ResponseRef) and use it in place of openapi3.Responses for field openapi3.Components.Responses.

v0.116.0

  • Dropped openapi3filter.DefaultOptions. Use &openapi3filter.Options{} directly instead.

v0.113.0

  • The string format email has been removed by default. To use it please call openapi3.DefineStringFormat("email", openapi3.FormatOfStringForEmail).
  • Field openapi3.T.Components is now a pointer.
  • Fields openapi3.Schema.AdditionalProperties and openapi3.Schema.AdditionalPropertiesAllowed are replaced by openapi3.Schema.AdditionalProperties.Schema and openapi3.Schema.AdditionalProperties.Has respectively.
  • Type openapi3.ExtensionProps is now just map[string]any and extensions are accessible through the Extensions field.

v0.112.0

  • (openapi3.ValidationOptions).ExamplesValidationDisabled has been unexported.
  • (openapi3.ValidationOptions).SchemaFormatValidationEnabled has been unexported.
  • (openapi3.ValidationOptions).SchemaPatternValidationDisabled has been unexported.

v0.111.0

  • Changed func (*_) Validate(ctx context.Context) error to func (*_) Validate(ctx context.Context, opts ...ValidationOption) error.
  • openapi3.WithValidationOptions(ctx context.Context, opts *ValidationOptions) context.Context prototype changed to openapi3.WithValidationOptions(ctx context.Context, opts ...ValidationOption) context.Context.

v0.101.0

  • openapi3.SchemaFormatValidationDisabled has been removed in favour of an option openapi3.EnableSchemaFormatValidation() passed to openapi3.T.Validate. The default behaviour is also now to not validate formats, as the OpenAPI spec mentions the format is an open value.

v0.84.0

  • The prototype of openapi3gen.NewSchemaRefForValue changed:
    • It no longer returns a map but that is still accessible under the field (*Generator).SchemaRefs.
    • It now takes in an additional argument (basically doc.Components.Schemas) which gets written to so $ref cycles can be properly handled.

v0.61.0

  • Renamed openapi2.Swagger to openapi2.T.
  • Renamed openapi2conv.FromV3Swagger to openapi2conv.FromV3.
  • Renamed openapi2conv.ToV3Swagger to openapi2conv.ToV3.
  • Renamed openapi3.LoadSwaggerFromData to openapi3.LoadFromData.
  • Renamed openapi3.LoadSwaggerFromDataWithPath to openapi3.LoadFromDataWithPath.
  • Renamed openapi3.LoadSwaggerFromFile to openapi3.LoadFromFile.
  • Renamed openapi3.LoadSwaggerFromURI to openapi3.LoadFromURI.
  • Renamed openapi3.NewSwaggerLoader to openapi3.NewLoader.
  • Renamed openapi3.Swagger to openapi3.T.
  • Renamed openapi3.SwaggerLoader to openapi3.Loader.
  • Renamed openapi3filter.ValidationHandler.SwaggerFile to openapi3filter.ValidationHandler.File.
  • Renamed routers.Route.Swagger to routers.Route.Spec.

v0.51.0

  • Type openapi3filter.Route moved to routers (and Route.Handler was dropped. See https://github.com/getkin/kin-openapi/issues/329)
  • Type openapi3filter.RouteError moved to routers (so did ErrPathNotFound and ErrMethodNotAllowed which are now RouteErrors)
  • Routers' FindRoute(...) method now takes only one argument: *http.Request
  • getkin/kin-openapi/openapi3filter.Router moved to getkin/kin-openapi/routers/legacy
  • openapi3filter.NewRouter() and its related WithSwaggerFromFile(string), WithSwagger(*openapi3.Swagger), AddSwaggerFromFile(string) and AddSwagger(*openapi3.Swagger) are all replaced with a single <router package>.NewRouter(*openapi3.Swagger)
    • NOTE: the NewRouter(doc) call now requires that the user ensures doc is valid (doc.Validate() != nil). This used to be asserted.

v0.47.0

Field (*openapi3.SwaggerLoader).LoadSwaggerFromURIFunc of type func(*openapi3.SwaggerLoader, *url.URL) (*openapi3.Swagger, error) was removed after the addition of the field (*openapi3.SwaggerLoader).ReadFromURIFunc of type func(*openapi3.SwaggerLoader, *url.URL) ([]byte, error).