Skip to content

Commit

Permalink
openapi3: correct implementations of JSONLookup (#876)
Browse files Browse the repository at this point in the history
  • Loading branch information
fenollp authored Nov 27, 2023
1 parent c1681a9 commit 4e7d031
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 166 deletions.
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

0 comments on commit 4e7d031

Please sign in to comment.