Merged in feature/s3integration (pull request #47)

Set Up S3 integration

* cfginterfaceandfirsts3funcs

* addlocalstack

* generallypassesfullsuite

* addedmultipleattemptedpings

* cleanup

* stabiliseplusskip
This commit is contained in:
Michael McGuinness
2025-02-05 12:52:41 +00:00
parent 9254b91d45
commit 92334ad1dd
838 changed files with 139249 additions and 6671 deletions
+7
View File
@@ -9,6 +9,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callback-object
type Callback struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
m map[string]*PathItem
}
@@ -52,3 +53,9 @@ func (callback *Callback) Validate(ctx context.Context, opts ...ValidationOption
return validateExtensions(ctx, callback.Extensions)
}
// UnmarshalJSON sets Callbacks to a copy of data.
func (callbacks *Callbacks) UnmarshalJSON(data []byte) (err error) {
*callbacks, _, err = unmarshalStringMapP[CallbackRef](data)
return
}
+2
View File
@@ -25,6 +25,7 @@ type (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#components-object
type Components struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Schemas Schemas `json:"schemas,omitempty" yaml:"schemas,omitempty"`
Parameters ParametersMap `json:"parameters,omitempty" yaml:"parameters,omitempty"`
@@ -94,6 +95,7 @@ func (components *Components) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "schemas")
delete(x.Extensions, "parameters")
delete(x.Extensions, "headers")
+3
View File
@@ -9,6 +9,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#contact-object
type Contact struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
URL string `json:"url,omitempty" yaml:"url,omitempty"`
@@ -50,6 +51,8 @@ func (contact *Contact) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "name")
delete(x.Extensions, "url")
delete(x.Extensions, "email")
+6
View File
@@ -122,3 +122,9 @@ func (content Content) Validate(ctx context.Context, opts ...ValidationOption) e
}
return nil
}
// UnmarshalJSON sets Content to a copy of data.
func (content *Content) UnmarshalJSON(data []byte) (err error) {
*content, _, err = unmarshalStringMapP[MediaType](data)
return
}
+5 -2
View File
@@ -9,9 +9,10 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#discriminator-object
type Discriminator struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
PropertyName string `json:"propertyName" yaml:"propertyName"` // required
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
PropertyName string `json:"propertyName" yaml:"propertyName"` // required
Mapping StringMap `json:"mapping,omitempty" yaml:"mapping,omitempty"`
}
// MarshalJSON returns the JSON encoding of Discriminator.
@@ -44,6 +45,8 @@ func (discriminator *Discriminator) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "propertyName")
delete(x.Extensions, "mapping")
if len(x.Extensions) == 0 {
+3
View File
@@ -11,6 +11,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#encoding-object
type Encoding struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
@@ -80,6 +81,8 @@ func (encoding *Encoding) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "contentType")
delete(x.Extensions, "headers")
delete(x.Extensions, "style")
+8
View File
@@ -10,6 +10,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#example-object
type Example struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
@@ -59,6 +60,7 @@ func (example *Example) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "summary")
delete(x.Extensions, "description")
delete(x.Extensions, "value")
@@ -83,3 +85,9 @@ func (example *Example) Validate(ctx context.Context, opts ...ValidationOption)
return validateExtensions(ctx, example.Extensions)
}
// UnmarshalJSON sets Examples to a copy of data.
func (examples *Examples) UnmarshalJSON(data []byte) (err error) {
*examples, _, err = unmarshalStringMapP[ExampleRef](data)
return
}
+2
View File
@@ -12,6 +12,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#external-documentation-object
type ExternalDocs struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
URL string `json:"url,omitempty" yaml:"url,omitempty"`
@@ -49,6 +50,7 @@ func (e *ExternalDocs) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "description")
delete(x.Extensions, "url")
if len(x.Extensions) == 0 {
+6
View File
@@ -94,3 +94,9 @@ func (header *Header) Validate(ctx context.Context, opts ...ValidationOption) er
}
return nil
}
// UnmarshalJSON sets Headers to a copy of data.
func (headers *Headers) UnmarshalJSON(data []byte) (err error) {
*headers, _, err = unmarshalStringMapP[HeaderRef](data)
return
}
+2
View File
@@ -10,6 +10,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#info-object
type Info struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Title string `json:"title" yaml:"title"` // Required
Description string `json:"description,omitempty" yaml:"description,omitempty"`
@@ -62,6 +63,7 @@ func (info *Info) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "title")
delete(x.Extensions, "description")
delete(x.Extensions, "termsOfService")
+2
View File
@@ -10,6 +10,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#license-object
type License struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Name string `json:"name" yaml:"name"` // Required
URL string `json:"url,omitempty" yaml:"url,omitempty"`
@@ -45,6 +46,7 @@ func (license *License) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "name")
delete(x.Extensions, "url")
if len(x.Extensions) == 0 {
+9
View File
@@ -11,6 +11,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#link-object
type Link struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
OperationID string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
@@ -66,6 +67,8 @@ func (link *Link) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "operationRef")
delete(x.Extensions, "operationId")
delete(x.Extensions, "description")
@@ -92,3 +95,9 @@ func (link *Link) Validate(ctx context.Context, opts ...ValidationOption) error
return validateExtensions(ctx, link.Extensions)
}
// UnmarshalJSON sets Links to a copy of data.
func (links *Links) UnmarshalJSON(data []byte) (err error) {
*links, _, err = unmarshalStringMapP[LinkRef](data)
return
}
+7 -4
View File
@@ -28,6 +28,9 @@ type Loader struct {
// IsExternalRefsAllowed enables visiting other files
IsExternalRefsAllowed bool
// IncludeOrigin specifies whether to include the origin of the OpenAPI elements
IncludeOrigin bool
// ReadFromURIFunc allows overriding the any file/URL reading func
ReadFromURIFunc ReadFromURIFunc
@@ -103,7 +106,7 @@ func (loader *Loader) loadSingleElementFromURI(ref string, rootPath *url.URL, el
if err != nil {
return nil, err
}
if err := unmarshal(data, element); err != nil {
if err := unmarshal(data, element, loader.IncludeOrigin); err != nil {
return nil, err
}
@@ -139,7 +142,7 @@ func (loader *Loader) LoadFromIoReader(reader io.Reader) (*T, error) {
func (loader *Loader) LoadFromData(data []byte) (*T, error) {
loader.resetVisitedPathItemRefs()
doc := &T{}
if err := unmarshal(data, doc); err != nil {
if err := unmarshal(data, doc, loader.IncludeOrigin); err != nil {
return nil, err
}
if err := loader.ResolveRefsIn(doc, nil); err != nil {
@@ -168,7 +171,7 @@ func (loader *Loader) loadFromDataWithPathInternal(data []byte, location *url.UR
doc := &T{}
loader.visitedDocuments[uri] = doc
if err := unmarshal(data, doc); err != nil {
if err := unmarshal(data, doc, loader.IncludeOrigin); err != nil {
return nil, err
}
@@ -422,7 +425,7 @@ func (loader *Loader) resolveComponent(doc *T, ref string, path *url.URL, resolv
if err2 != nil {
return nil, nil, err
}
if err2 = unmarshal(data, &cursor); err2 != nil {
if err2 = unmarshal(data, &cursor, loader.IncludeOrigin); err2 != nil {
return nil, nil, err
}
if cursor, err2 = drill(cursor); err2 != nil || cursor == nil {
+33
View File
@@ -125,6 +125,17 @@ func (responses *Responses) UnmarshalJSON(data []byte) (err error) {
continue
}
if k == originKey {
var data []byte
if data, err = json.Marshal(v); err != nil {
return
}
if err = json.Unmarshal(data, &x.Origin); err != nil {
return
}
continue
}
var data []byte
if data, err = json.Marshal(v); err != nil {
return
@@ -256,6 +267,17 @@ func (callback *Callback) UnmarshalJSON(data []byte) (err error) {
continue
}
if k == originKey {
var data []byte
if data, err = json.Marshal(v); err != nil {
return
}
if err = json.Unmarshal(data, &x.Origin); err != nil {
return
}
continue
}
var data []byte
if data, err = json.Marshal(v); err != nil {
return
@@ -387,6 +409,17 @@ func (paths *Paths) UnmarshalJSON(data []byte) (err error) {
continue
}
if k == originKey {
var data []byte
if data, err = json.Marshal(v); err != nil {
return
}
if err = json.Unmarshal(data, &x.Origin); err != nil {
return
}
continue
}
var data []byte
if data, err = json.Marshal(v); err != nil {
return
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"fmt"
"strings"
"github.com/invopop/yaml"
"github.com/oasdiff/yaml"
)
func unmarshalError(jsonUnmarshalErr error) error {
@@ -16,7 +16,7 @@ func unmarshalError(jsonUnmarshalErr error) error {
return jsonUnmarshalErr
}
func unmarshal(data []byte, v any) error {
func unmarshal(data []byte, v any, includeOrigin bool) error {
var jsonErr, yamlErr error
// See https://github.com/getkin/kin-openapi/issues/680
@@ -25,7 +25,7 @@ func unmarshal(data []byte, v any) error {
}
// UnmarshalStrict(data, v) TODO: investigate how ymlv3 handles duplicate map keys
if yamlErr = yaml.Unmarshal(data, v); yamlErr == nil {
if yamlErr = yaml.UnmarshalWithOrigin(data, v, includeOrigin); yamlErr == nil {
return nil
}
+2
View File
@@ -14,6 +14,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#media-type-object
type MediaType struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"`
Example any `json:"example,omitempty" yaml:"example,omitempty"`
@@ -101,6 +102,7 @@ func (mediaType *MediaType) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "schema")
delete(x.Extensions, "example")
delete(x.Extensions, "examples")
+2
View File
@@ -14,6 +14,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object
type Operation struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
// Optional tags for documentation.
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
@@ -116,6 +117,7 @@ func (operation *Operation) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "tags")
delete(x.Extensions, "summary")
delete(x.Extensions, "description")
+17
View File
@@ -0,0 +1,17 @@
package openapi3
const originKey = "origin"
// Origin contains the origin of a collection.
// Key is the location of the collection itself.
// Fields is a map of the location of each field in the collection.
type Origin struct {
Key *Location `json:"key,omitempty" yaml:"key,omitempty"`
Fields map[string]Location `json:"fields,omitempty" yaml:"fields,omitempty"`
}
// Location is a struct that contains the location of a field.
type Location struct {
Line int `json:"line,omitempty" yaml:"line,omitempty"`
Column int `json:"column,omitempty" yaml:"column,omitempty"`
}
+8
View File
@@ -73,6 +73,7 @@ func (parameters Parameters) Validate(ctx context.Context, opts ...ValidationOpt
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameter-object
type Parameter struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
In string `json:"in,omitempty" yaml:"in,omitempty"`
@@ -216,6 +217,7 @@ func (parameter *Parameter) UnmarshalJSON(data []byte) error {
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "name")
delete(x.Extensions, "in")
delete(x.Extensions, "description")
@@ -414,3 +416,9 @@ func (parameter *Parameter) Validate(ctx context.Context, opts ...ValidationOpti
return validateExtensions(ctx, parameter.Extensions)
}
// UnmarshalJSON sets ParametersMap to a copy of data.
func (parametersMap *ParametersMap) UnmarshalJSON(data []byte) (err error) {
*parametersMap, _, err = unmarshalStringMapP[ParameterRef](data)
return
}
+2
View File
@@ -12,6 +12,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#path-item-object
type PathItem struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
@@ -98,6 +99,7 @@ func (pathItem *PathItem) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "$ref")
delete(x.Extensions, "summary")
delete(x.Extensions, "description")
+1
View File
@@ -11,6 +11,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#paths-object
type Paths struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
m map[string]*PathItem
}
+2 -1
View File
@@ -5,5 +5,6 @@ package openapi3
// Ref is specified by OpenAPI/Swagger 3.0 standard.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#reference-object
type Ref struct {
Ref string `json:"$ref" yaml:"$ref"`
Ref string `json:"$ref" yaml:"$ref"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
}
+18
View File
@@ -19,6 +19,7 @@ type CallbackRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Callback
@@ -72,6 +73,7 @@ func (x *CallbackRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -155,6 +157,7 @@ type ExampleRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Example
@@ -208,6 +211,7 @@ func (x *ExampleRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -291,6 +295,7 @@ type HeaderRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Header
@@ -344,6 +349,7 @@ func (x *HeaderRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -427,6 +433,7 @@ type LinkRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Link
@@ -480,6 +487,7 @@ func (x *LinkRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -563,6 +571,7 @@ type ParameterRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Parameter
@@ -616,6 +625,7 @@ func (x *ParameterRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -699,6 +709,7 @@ type RequestBodyRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *RequestBody
@@ -752,6 +763,7 @@ func (x *RequestBodyRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -835,6 +847,7 @@ type ResponseRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Response
@@ -888,6 +901,7 @@ func (x *ResponseRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -971,6 +985,7 @@ type SchemaRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *Schema
@@ -1024,6 +1039,7 @@ func (x *SchemaRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
@@ -1107,6 +1123,7 @@ type SecuritySchemeRef struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *SecurityScheme
@@ -1160,6 +1177,7 @@ func (x *SecuritySchemeRef) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
+2
View File
@@ -19,6 +19,7 @@ type {{ $type.Name }}Ref struct {
// Extensions only captures fields starting with 'x-' as no other fields
// are allowed by the openapi spec.
Extensions map[string]any
Origin *Origin
Ref string
Value *{{ $type.Name }}
@@ -72,6 +73,7 @@ func (x *{{ $type.Name }}Ref) UnmarshalJSON(data []byte) error {
var refOnly Ref
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
x.Ref = refOnly.Ref
x.Origin = refOnly.Origin
if len(extra) != 0 {
x.extra = make([]string, 0, len(extra))
for key := range extra {
+8
View File
@@ -10,6 +10,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#request-body-object
type RequestBody struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
@@ -108,6 +109,7 @@ func (requestBody *RequestBody) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "description")
delete(x.Extensions, "required")
delete(x.Extensions, "content")
@@ -136,3 +138,9 @@ func (requestBody *RequestBody) Validate(ctx context.Context, opts ...Validation
return validateExtensions(ctx, requestBody.Extensions)
}
// UnmarshalJSON sets RequestBodies to a copy of data.
func (requestBodies *RequestBodies) UnmarshalJSON(data []byte) (err error) {
*requestBodies, _, err = unmarshalStringMapP[RequestBodyRef](data)
return
}
+9
View File
@@ -12,6 +12,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responses-object
type Responses struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"-" yaml:"-"`
m map[string]*ResponseRef
}
@@ -102,6 +103,7 @@ func (responses *Responses) Validate(ctx context.Context, opts ...ValidationOpti
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#response-object
type Response struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Description *string `json:"description,omitempty" yaml:"description,omitempty"`
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
@@ -171,6 +173,7 @@ func (response *Response) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "description")
delete(x.Extensions, "headers")
delete(x.Extensions, "content")
@@ -225,3 +228,9 @@ func (response *Response) Validate(ctx context.Context, opts ...ValidationOption
return validateExtensions(ctx, response.Extensions)
}
// UnmarshalJSON sets ResponseBodies to a copy of data.
func (responseBodies *ResponseBodies) UnmarshalJSON(data []byte) (err error) {
*responseBodies, _, err = unmarshalStringMapP[ResponseRef](data)
return
}
+8
View File
@@ -81,6 +81,7 @@ func (s SchemaRefs) JSONLookup(token string) (any, error) {
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schema-object
type Schema struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
OneOf SchemaRefs `json:"oneOf,omitempty" yaml:"oneOf,omitempty"`
AnyOf SchemaRefs `json:"anyOf,omitempty" yaml:"anyOf,omitempty"`
@@ -411,6 +412,7 @@ func (schema *Schema) UnmarshalJSON(data []byte) error {
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "oneOf")
delete(x.Extensions, "anyOf")
delete(x.Extensions, "allOf")
@@ -2244,3 +2246,9 @@ func RegisterArrayUniqueItemsChecker(fn SliceUniqueItemsChecker) {
func unsupportedFormat(format string) error {
return fmt.Errorf("unsupported 'format' value %q", format)
}
// UnmarshalJSON sets Schemas to a copy of data.
func (schemas *Schemas) UnmarshalJSON(data []byte) (err error) {
*schemas, _, err = unmarshalStringMapP[SchemaRef](data)
return
}
+4 -2
View File
@@ -41,10 +41,10 @@ const (
FormatOfStringByte = `(^$|^[a-zA-Z0-9+/\-_]*=*$)`
// FormatOfStringDate is a RFC3339 date format regexp, for example "2017-07-21".
FormatOfStringDate = `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)$`
FormatOfStringDate = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])$`
// FormatOfStringDateTime is a RFC3339 date-time format regexp, for example "2017-07-21T17:32:28Z".
FormatOfStringDateTime = `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$`
FormatOfStringDateTime = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])T([0-1][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$`
)
func init() {
@@ -131,12 +131,14 @@ func DefineIntegerFormatValidator(name string, validator IntegerFormatValidator)
}
// DefineStringFormat defines a regexp pattern for a given string format
//
// Deprecated: Use openapi3.DefineStringFormatValidator(name, NewRegexpFormatValidator(pattern)) instead.
func DefineStringFormat(name string, pattern string) {
DefineStringFormatValidator(name, NewRegexpFormatValidator(pattern))
}
// DefineStringFormatCallback defines a callback function for a given string format
//
// Deprecated: Use openapi3.DefineStringFormatValidator(name, NewCallbackValidator(fn)) instead.
func DefineStringFormatCallback(name string, callback func(string) error) {
DefineStringFormatValidator(name, NewCallbackValidator(callback))
@@ -49,3 +49,9 @@ func (security *SecurityRequirement) Validate(ctx context.Context, opts ...Valid
return nil
}
// UnmarshalJSON sets SecurityRequirement to a copy of data.
func (security *SecurityRequirement) UnmarshalJSON(data []byte) (err error) {
*security, _, err = unmarshalStringMap[[]string](data)
return
}
+17 -4
View File
@@ -12,6 +12,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-scheme-object
type SecurityScheme struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
@@ -100,6 +101,7 @@ func (ss *SecurityScheme) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "type")
delete(x.Extensions, "description")
delete(x.Extensions, "name")
@@ -216,6 +218,7 @@ func (ss *SecurityScheme) Validate(ctx context.Context, opts ...ValidationOption
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauth-flows-object
type OAuthFlows struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Implicit *OAuthFlow `json:"implicit,omitempty" yaml:"implicit,omitempty"`
Password *OAuthFlow `json:"password,omitempty" yaml:"password,omitempty"`
@@ -270,6 +273,7 @@ func (flows *OAuthFlows) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "implicit")
delete(x.Extensions, "password")
delete(x.Extensions, "clientCredentials")
@@ -316,11 +320,12 @@ func (flows *OAuthFlows) Validate(ctx context.Context, opts ...ValidationOption)
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauth-flow-object
type OAuthFlow struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
Scopes map[string]string `json:"scopes" yaml:"scopes"` // required
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
Scopes StringMap `json:"scopes" yaml:"scopes"` // required
}
// MarshalJSON returns the JSON encoding of OAuthFlow.
@@ -359,6 +364,8 @@ func (flow *OAuthFlow) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "authorizationUrl")
delete(x.Extensions, "tokenUrl")
delete(x.Extensions, "refreshUrl")
@@ -427,3 +434,9 @@ func (flow *OAuthFlow) validate(ctx context.Context, typ oAuthFlowType, opts ...
return flow.Validate(ctx, opts...)
}
// UnmarshalJSON sets SecuritySchemes to a copy of data.
func (securitySchemes *SecuritySchemes) UnmarshalJSON(data []byte) (err error) {
*securitySchemes, _, err = unmarshalStringMapP[SecuritySchemeRef](data)
return
}
+5 -2
View File
@@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"net/url"
"sort"
"strings"
@@ -52,6 +51,7 @@ func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string)
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-object
type Server struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
URL string `json:"url" yaml:"url"` // Required
Description string `json:"description,omitempty" yaml:"description,omitempty"`
@@ -115,6 +115,7 @@ func (server *Server) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "url")
delete(x.Extensions, "description")
delete(x.Extensions, "variables")
@@ -172,7 +173,7 @@ func (server Server) MatchRawURL(input string) ([]string, string, bool) {
} else if ns < 0 {
i = np
} else {
i = int(math.Min(float64(np), float64(ns)))
i = min(np, ns)
}
if i < 0 {
i = len(input)
@@ -235,6 +236,7 @@ func (server *Server) Validate(ctx context.Context, opts ...ValidationOption) (e
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-variable-object
type ServerVariable struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Enum []string `json:"enum,omitempty" yaml:"enum,omitempty"`
Default string `json:"default,omitempty" yaml:"default,omitempty"`
@@ -276,6 +278,7 @@ func (serverVariable *ServerVariable) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "enum")
delete(x.Extensions, "default")
delete(x.Extensions, "description")
+76
View File
@@ -0,0 +1,76 @@
package openapi3
import "encoding/json"
// StringMap is a map[string]string that ignores the origin in the underlying json representation.
type StringMap map[string]string
// UnmarshalJSON sets StringMap to a copy of data.
func (stringMap *StringMap) UnmarshalJSON(data []byte) (err error) {
*stringMap, _, err = unmarshalStringMap[string](data)
return
}
// unmarshalStringMapP unmarshals given json into a map[string]*V
func unmarshalStringMapP[V any](data []byte) (map[string]*V, *Origin, error) {
var m map[string]any
if err := json.Unmarshal(data, &m); err != nil {
return nil, nil, err
}
origin, err := deepCast[Origin](m[originKey])
if err != nil {
return nil, nil, err
}
delete(m, originKey)
result := make(map[string]*V, len(m))
for k, v := range m {
value, err := deepCast[V](v)
if err != nil {
return nil, nil, err
}
result[k] = value
}
return result, origin, nil
}
// unmarshalStringMap unmarshals given json into a map[string]V
func unmarshalStringMap[V any](data []byte) (map[string]V, *Origin, error) {
var m map[string]any
if err := json.Unmarshal(data, &m); err != nil {
return nil, nil, err
}
origin, err := deepCast[Origin](m[originKey])
if err != nil {
return nil, nil, err
}
delete(m, originKey)
result := make(map[string]V, len(m))
for k, v := range m {
value, err := deepCast[V](v)
if err != nil {
return nil, nil, err
}
result[k] = *value
}
return result, origin, nil
}
// deepCast casts any value to a value of type V.
func deepCast[V any](value any) (*V, error) {
data, err := json.Marshal(value)
if err != nil {
return nil, err
}
var result V
if err = json.Unmarshal(data, &result); err != nil {
return nil, err
}
return &result, nil
}
+2
View File
@@ -34,6 +34,7 @@ func (tags Tags) Validate(ctx context.Context, opts ...ValidationOption) error {
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#tag-object
type Tag struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
@@ -75,6 +76,7 @@ func (t *Tag) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "name")
delete(x.Extensions, "description")
delete(x.Extensions, "externalDocs")
+2
View File
@@ -9,6 +9,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-object
type XML struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
@@ -58,6 +59,7 @@ func (xml *XML) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "name")
delete(x.Extensions, "namespace")
delete(x.Extensions, "prefix")