Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openapi3: correct implementations of JSONLookup #876

Merged
merged 1 commit into from
Nov 27, 2023
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
20 changes: 0 additions & 20 deletions openapi3/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,9 @@ package openapi3

import (
"context"
"fmt"
"sort"

"github.com/go-openapi/jsonpointer"
)

type Callbacks map[string]*CallbackRef

var _ jsonpointer.JSONPointable = (*Callbacks)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (c Callbacks) JSONLookup(token string) (interface{}, error) {
ref, ok := c[token]
if ref == nil || !ok {
return nil, fmt.Errorf("object has no field %q", token)
}

if ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
return ref.Value, nil
}

// Callback is specified by OpenAPI/Swagger standard version 3.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callback-object
type Callback map[string]*PathItem
Expand Down
131 changes: 131 additions & 0 deletions openapi3/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ import (
"encoding/json"
"fmt"
"sort"

"github.com/go-openapi/jsonpointer"
)

type (
Callbacks map[string]*CallbackRef
Examples map[string]*ExampleRef
Headers map[string]*HeaderRef
Links map[string]*LinkRef
ParametersMap map[string]*ParameterRef
RequestBodies map[string]*RequestBodyRef
ResponseBodies map[string]*ResponseRef
Schemas map[string]*SchemaRef
SecuritySchemes map[string]*SecuritySchemeRef
)

// Components is specified by OpenAPI/Swagger standard version 3.
Expand Down Expand Up @@ -228,3 +242,120 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp

return validateExtensions(ctx, components.Extensions)
}

var _ jsonpointer.JSONPointable = (*Schemas)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m Schemas) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no schema %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*ParametersMap)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m ParametersMap) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no parameter %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*Headers)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m Headers) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no header %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*RequestBodyRef)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m RequestBodies) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no request body %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*ResponseRef)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m ResponseBodies) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no response body %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*SecuritySchemes)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m SecuritySchemes) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no security scheme body %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*Examples)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m Examples) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no example body %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*Links)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m Links) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no link body %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}

var _ jsonpointer.JSONPointable = (*Callbacks)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (m Callbacks) JSONLookup(token string) (interface{}, error) {
if v, ok := m[token]; !ok || v == nil {
return nil, fmt.Errorf("no callback body %q", token)
} else if ref := v.Ref; ref != "" {
return &Ref{Ref: ref}, nil
} else {
return v.Value, nil
}
}
20 changes: 0 additions & 20 deletions openapi3/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,8 @@ import (
"context"
"encoding/json"
"errors"
"fmt"

"github.com/go-openapi/jsonpointer"
)

type Examples map[string]*ExampleRef

var _ jsonpointer.JSONPointable = (*Examples)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (e Examples) JSONLookup(token string) (interface{}, error) {
ref, ok := e[token]
if ref == nil || !ok {
return nil, fmt.Errorf("object has no field %q", token)
}

if ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
return ref.Value, nil
}

// Example is specified by OpenAPI/Swagger 3.0 standard.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#example-object
type Example struct {
Expand Down
17 changes: 0 additions & 17 deletions openapi3/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,6 @@ import (
"github.com/go-openapi/jsonpointer"
)

type Headers map[string]*HeaderRef

var _ jsonpointer.JSONPointable = (*Headers)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (h Headers) JSONLookup(token string) (interface{}, error) {
ref, ok := h[token]
if ref == nil || !ok {
return nil, fmt.Errorf("object has no field %q", token)
}

if ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
return ref.Value, nil
}

// Header is specified by OpenAPI/Swagger 3.0 standard.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#header-object
type Header struct {
Expand Down
19 changes: 0 additions & 19 deletions openapi3/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"

"github.com/go-openapi/jsonpointer"
)

type Links map[string]*LinkRef

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (links Links) JSONLookup(token string) (interface{}, error) {
ref, ok := links[token]
if !ok {
return nil, fmt.Errorf("object has no field %q", token)
}

if ref != nil && ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
return ref.Value, nil
}

var _ jsonpointer.JSONPointable = (*Links)(nil)

// Link is specified by OpenAPI/Swagger standard version 3.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#link-object
type Link struct {
Expand Down
29 changes: 29 additions & 0 deletions openapi3/openapi3.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"

"github.com/go-openapi/jsonpointer"
)

// T is the root of an OpenAPI v3 document
Expand All @@ -24,6 +26,33 @@ type T struct {
visited visitedComponent
}

var _ jsonpointer.JSONPointable = (*T)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (doc *T) JSONLookup(token string) (interface{}, error) {
switch token {
case "openapi":
return doc.OpenAPI, nil
case "components":
return doc.Components, nil
case "info":
return doc.Info, nil
case "paths":
return doc.Paths, nil
case "security":
return doc.Security, nil
case "servers":
return doc.Servers, nil
case "tags":
return doc.Tags, nil
case "externalDocs":
return doc.ExternalDocs, nil
}

v, _, err := jsonpointer.GetForToken(doc.Extensions, token)
return v, err
}

// MarshalJSON returns the JSON encoding of T.
func (doc T) MarshalJSON() ([]byte, error) {
m := make(map[string]interface{}, 4+len(doc.Extensions))
Expand Down
19 changes: 0 additions & 19 deletions openapi3/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,6 @@ import (
"github.com/go-openapi/jsonpointer"
)

type ParametersMap map[string]*ParameterRef

var _ jsonpointer.JSONPointable = (*ParametersMap)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (p ParametersMap) JSONLookup(token string) (interface{}, error) {
ref, ok := p[token]
if ref == nil || !ok {
return nil, fmt.Errorf("object has no field %q", token)
}

if ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
return ref.Value, nil
}

// Parameters is specified by OpenAPI/Swagger 3.0 standard.
type Parameters []*ParameterRef

Expand All @@ -39,13 +22,11 @@ func (p Parameters) JSONLookup(token string) (interface{}, error) {
if err != nil {
return nil, err
}

if index < 0 || index >= len(p) {
return nil, fmt.Errorf("index %d out of bounds of array of length %d", index, len(p))
}

ref := p[index]

if ref != nil && ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
Expand Down
3 changes: 3 additions & 0 deletions openapi3/refs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,15 @@ components:
- type: integer
format: int32
`[1:])

loader := NewLoader()
doc, err := loader.LoadFromData(spec)
require.NoError(t, err)
require.NotNil(t, doc)

err = doc.Validate(loader.Context)
require.NoError(t, err)

var ptr jsonpointer.Pointer
var v interface{}
var kind reflect.Kind
Expand Down
20 changes: 0 additions & 20 deletions openapi3/request_body.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,8 @@ import (
"context"
"encoding/json"
"errors"
"fmt"

"github.com/go-openapi/jsonpointer"
)

type RequestBodies map[string]*RequestBodyRef

var _ jsonpointer.JSONPointable = (*RequestBodyRef)(nil)

// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (r RequestBodies) JSONLookup(token string) (interface{}, error) {
ref, ok := r[token]
if !ok {
return nil, fmt.Errorf("object has no field %q", token)
}

if ref != nil && ref.Ref != "" {
return &Ref{Ref: ref.Ref}, nil
}
return ref.Value, nil
}

// RequestBody is specified by OpenAPI/Swagger 3.0 standard.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#request-body-object
type RequestBody struct {
Expand Down
Loading
Loading