Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 178 additions & 2 deletions .github/docs/openapi3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,30 @@ package openapi3 // import "github.com/getkin/kin-openapi/openapi3"

Package openapi3 parses and writes OpenAPI 3 specification documents.

See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md
Supports both OpenAPI 3.0 and OpenAPI 3.1:
- OpenAPI 3.0.x:
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md
- OpenAPI 3.1.x:
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md

OpenAPI 3.1 Features:
- Type arrays with null support (e.g., ["string", "null"])
- JSON Schema 2020-12 keywords (const, examples, prefixItems, etc.)
- Webhooks for defining callback operations
- JSON Schema dialect specification
- SPDX license identifiers

The implementation maintains 100% backward compatibility with OpenAPI 3.0.

For OpenAPI 3.1 validation, use the JSON Schema 2020-12 validator option:

schema.VisitJSON(value, openapi3.EnableJSONSchema2020())

Version detection is available via helper methods:

if doc.IsOpenAPI3_1() {
// Handle OpenAPI 3.1 specific features
}

Code generated by go generate; DO NOT EDIT.

Expand Down Expand Up @@ -680,7 +703,8 @@ type Info struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`

Title string `json:"title" yaml:"title"` // Required
Title string `json:"title" yaml:"title"` // Required
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"` // OpenAPI 3.1
Description string `json:"description,omitempty" yaml:"description,omitempty"`
TermsOfService string `json:"termsOfService,omitempty" yaml:"termsOfService,omitempty"`
Contact *Contact `json:"contact,omitempty" yaml:"contact,omitempty"`
Expand All @@ -689,6 +713,8 @@ type Info struct {
}
Info is specified by OpenAPI/Swagger standard version 3. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#info-object
and
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#info-object

func (info Info) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoding of Info.
Expand All @@ -711,9 +737,15 @@ type License struct {

Name string `json:"name" yaml:"name"` // Required
URL string `json:"url,omitempty" yaml:"url,omitempty"`

// Identifier is an SPDX license expression for the API (OpenAPI 3.1)
// Either url or identifier can be specified, not both
Identifier string `json:"identifier,omitempty" yaml:"identifier,omitempty"`
}
License is specified by OpenAPI/Swagger standard version 3. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#license-object
and
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#license-object

func (license License) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoding of License.
Expand Down Expand Up @@ -1611,6 +1643,19 @@ type Schema struct {
MaxProps *uint64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
AdditionalProperties AdditionalProperties `json:"additionalProperties,omitempty" yaml:"additionalProperties,omitempty"`
Discriminator *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`

// OpenAPI 3.1 / JSON Schema 2020-12 fields
Const any `json:"const,omitempty" yaml:"const,omitempty"`
Examples []any `json:"examples,omitempty" yaml:"examples,omitempty"`
PrefixItems []*SchemaRef `json:"prefixItems,omitempty" yaml:"prefixItems,omitempty"`
Contains *SchemaRef `json:"contains,omitempty" yaml:"contains,omitempty"`
MinContains *uint64 `json:"minContains,omitempty" yaml:"minContains,omitempty"`
MaxContains *uint64 `json:"maxContains,omitempty" yaml:"maxContains,omitempty"`
PatternProperties Schemas `json:"patternProperties,omitempty" yaml:"patternProperties,omitempty"`
DependentSchemas Schemas `json:"dependentSchemas,omitempty" yaml:"dependentSchemas,omitempty"`
PropertyNames *SchemaRef `json:"propertyNames,omitempty" yaml:"propertyNames,omitempty"`
UnevaluatedItems *SchemaRef `json:"unevaluatedItems,omitempty" yaml:"unevaluatedItems,omitempty"`
UnevaluatedProperties *SchemaRef `json:"unevaluatedProperties,omitempty" yaml:"unevaluatedProperties,omitempty"`
}
Schema is specified by OpenAPI/Swagger 3.0 standard. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schema-object
Expand Down Expand Up @@ -1847,6 +1892,12 @@ func EnableFormatValidation() SchemaValidationOption
validating documents that mention schema formats that are not defined by the
OpenAPIv3 specification.

func EnableJSONSchema2020() SchemaValidationOption
EnableJSONSchema2020 enables JSON Schema 2020-12 compliant validation.
This enables support for OpenAPI 3.1 and JSON Schema 2020-12 features.
When enabled, validation uses the jsonschema library instead of the built-in
validator.

func FailFast() SchemaValidationOption
FailFast returns schema validation errors quicker.

Expand Down Expand Up @@ -2102,10 +2153,20 @@ type T struct {
Tags Tags `json:"tags,omitempty" yaml:"tags,omitempty"`
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`

// OpenAPI 3.1.x specific fields
// Webhooks are a new feature in OpenAPI 3.1 that allow APIs to define callback operations
Webhooks map[string]*PathItem `json:"webhooks,omitempty" yaml:"webhooks,omitempty"`

// JSONSchemaDialect allows specifying the default JSON Schema dialect for Schema Objects
// See https://spec.openapis.org/oas/v3.1.0#schema-object
JSONSchemaDialect string `json:"jsonSchemaDialect,omitempty" yaml:"jsonSchemaDialect,omitempty"`

// Has unexported fields.
}
T is the root of an OpenAPI v3 document See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#openapi-object
and
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#openapi-object

func (doc *T) AddOperation(path string, method string, operation *Operation)

Expand All @@ -2126,6 +2187,12 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(*T, Comp

doc.InternalizeRefs(context.Background(), nil)

func (doc *T) IsOpenAPI3_0() bool
IsOpenAPI3_0 returns true if the document is OpenAPI 3.0.x

func (doc *T) IsOpenAPI3_1() bool
IsOpenAPI3_1 returns true if the document is OpenAPI 3.1.x

func (doc *T) JSONLookup(token string) (any, error)
JSONLookup implements
https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
Expand All @@ -2143,6 +2210,9 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error
Validate returns an error if T does not comply with the OpenAPI spec.
Validations Options can be provided to modify the validation behavior.

func (doc *T) Version() string
Version returns the major.minor version of the OpenAPI document

type Tag struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
Expand Down Expand Up @@ -2175,18 +2245,124 @@ func (tags Tags) Validate(ctx context.Context, opts ...ValidationOption) error
Validate returns an error if Tags does not comply with the OpenAPI spec.

type Types []string
Types represents the type(s) of a schema.

In OpenAPI 3.0, this is typically a single type (e.g., "string"). In OpenAPI
3.1, it can be an array of types (e.g., ["string", "null"]).

Serialization behavior:
- Single type: serializes as a string (e.g., "string")
- Multiple types: serializes as an array (e.g., ["string", "null"])
- Accepts both string and array formats when unmarshaling

Example OpenAPI 3.0 (single type):

schema := &Schema{Type: &Types{"string"}}
// JSON: {"type": "string"}

Example OpenAPI 3.1 (type array):

schema := &Schema{Type: &Types{"string", "null"}}
// JSON: {"type": ["string", "null"]}

func (pTypes *Types) Includes(typ string) bool
Includes returns true if the given type is included in the type array.
Returns false if types is nil.

Example:

types := &Types{"string", "null"}
types.Includes("string") // true
types.Includes("null") // true
types.Includes("number") // false

func (types *Types) IncludesNull() bool
IncludesNull returns true if the type array includes "null". This is useful
for OpenAPI 3.1 where null is a first-class type.

Example:

types := &Types{"string", "null"}
types.IncludesNull() // true

types = &Types{"string"}
types.IncludesNull() // false

func (types *Types) Is(typ string) bool
Is returns true if the schema has exactly one type and it matches the given
type. This is useful for OpenAPI 3.0 style single-type checks.

Example:

types := &Types{"string"}
types.Is("string") // true
types.Is("number") // false

types = &Types{"string", "null"}
types.Is("string") // false (multiple types)

func (types *Types) IsEmpty() bool
IsEmpty returns true if no types are specified (nil or empty array).
When a schema has no type specified, it permits any type.

Example:

var nilTypes *Types
nilTypes.IsEmpty() // true

types := &Types{}
types.IsEmpty() // true

types = &Types{"string"}
types.IsEmpty() // false

func (types *Types) IsMultiple() bool
IsMultiple returns true if multiple types are specified. This is an OpenAPI
3.1 feature that enables type arrays.

Example:

types := &Types{"string"}
types.IsMultiple() // false

types = &Types{"string", "null"}
types.IsMultiple() // true

func (types *Types) IsSingle() bool
IsSingle returns true if exactly one type is specified.

Example:

types := &Types{"string"}
types.IsSingle() // true

types = &Types{"string", "null"}
types.IsSingle() // false

func (pTypes *Types) MarshalJSON() ([]byte, error)

func (pTypes *Types) MarshalYAML() (any, error)

func (types *Types) Permits(typ string) bool
Permits returns true if the given type is permitted. Returns true if types
is nil (any type allowed), otherwise checks if the type is included.

Example:

var nilTypes *Types
nilTypes.Permits("anything") // true (nil permits everything)

types := &Types{"string"}
types.Permits("string") // true
types.Permits("number") // false

func (types *Types) Slice() []string
Slice returns the types as a string slice. Returns nil if types is nil.

Example:

types := &Types{"string", "null"}
slice := types.Slice() // []string{"string", "null"}

func (types *Types) UnmarshalJSON(data []byte) error

Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Run tests

on:
pull_request:
push:
branches:
- master

env:
TIMEOUT: 20m
BRANCH_NAME: ${{ github.base_ref || github.ref_name }} # base_ref for PRs is 'master', but merges read in ref_name

jobs:
lint:
runs-on: ubuntu-latest
if: ${{ !github.event.pull_request.draft }}
steps:
- name: "Checkout PR"
uses: TykTechnologies/github-actions/.github/actions/checkout-pr@main
with:
token: ${{ secrets.ORG_GH_TOKEN }}

- name: "Get base ref"
run: |
git fetch origin ${{ env.BRANCH_NAME }}
git rev-parse origin/${{ env.BRANCH_NAME }}

- name: Setup Golang
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache-dependency-path: go.sum

- name: golangci-lint
uses: golangci/golangci-lint-action@v8
timeout-minutes: 20
with:
version: v2.8.0
only-new-issues: ${{ github.event_name == 'pull_request' }}
# Output formats configured in .golangci.yml (v2 approach)
# Generates: text to stdout + checkstyle JSON for SonarQube
args: -v ./...
skip-cache: false
skip-save-cache: false

- uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: golangcilint
retention-days: 1
path: |
golangci-lint-report.json

unit-tests:
runs-on: ubuntu-latest
outputs:
latest-version: ${{ steps.get-latest-version.outputs.version }}
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}

- name: Setup Golang
uses: actions/setup-go@v5
with:
go-version: 1.24.x

- name: Run unit tests
env:
GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: go test ./...
Loading