forked from ebhomengo/niki
112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
package spec
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Ref is a simple object to allow referencing other components in the OpenAPI document, internally and externally.
|
|
// The $ref string value contains a URI [RFC3986], which identifies the location of the value being referenced.
|
|
// See the rules for resolving Relative References.
|
|
//
|
|
// https://spec.openapis.org/oas/v3.1.0#reference-object
|
|
//
|
|
// Example:
|
|
//
|
|
// $ref: '#/components/schemas/Pet'
|
|
type Ref struct {
|
|
// REQUIRED.
|
|
// The reference identifier.
|
|
// This MUST be in the form of a URI.
|
|
Ref string `json:"$ref" yaml:"$ref"`
|
|
// A short summary which by default SHOULD override that of the referenced component.
|
|
// If the referenced object-type does not allow a summary field, then this field has no effect.
|
|
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
|
// A description which by default SHOULD override that of the referenced component.
|
|
// CommonMark syntax MAY be used for rich text representation.
|
|
// If the referenced object-type does not allow a description field, then this field has no effect.
|
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
|
}
|
|
|
|
// NewRef creates an object of Ref type.
|
|
func NewRef(ref string) *Ref {
|
|
return &Ref{
|
|
Ref: ref,
|
|
}
|
|
}
|
|
|
|
// RefOrSpec holds either Ref or any OpenAPI spec type.
|
|
//
|
|
// NOTE: The Ref object takes precedent over Spec if using json or yaml Marshal and Unmarshal functions.
|
|
type RefOrSpec[T any] struct {
|
|
Ref *Ref `json:"-" yaml:"-"`
|
|
Spec *T `json:"-" yaml:"-"`
|
|
}
|
|
|
|
// NewRefOrSpec creates an object of RefOrSpec type for either Ref or Spec
|
|
func NewRefOrSpec[T any](ref *Ref, spec *T) *RefOrSpec[T] {
|
|
o := RefOrSpec[T]{}
|
|
switch {
|
|
case ref != nil:
|
|
o.Ref = ref
|
|
case spec != nil:
|
|
o.Spec = spec
|
|
}
|
|
return &o
|
|
}
|
|
|
|
// MarshalJSON implements json.Marshaler interface.
|
|
func (o *RefOrSpec[T]) MarshalJSON() ([]byte, error) {
|
|
var v any
|
|
if o.Ref != nil {
|
|
v = o.Ref
|
|
} else {
|
|
v = o.Spec
|
|
}
|
|
data, err := json.Marshal(&v)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%T: %w", o.Spec, err)
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler interface.
|
|
func (o *RefOrSpec[T]) UnmarshalJSON(data []byte) error {
|
|
if json.Unmarshal(data, &o.Ref) == nil && o.Ref.Ref != "" {
|
|
o.Spec = nil
|
|
return nil
|
|
}
|
|
|
|
o.Ref = nil
|
|
if err := json.Unmarshal(data, &o.Spec); err != nil {
|
|
return fmt.Errorf("%T: %w", o.Spec, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MarshalYAML implements yaml.Marshaler interface.
|
|
func (o *RefOrSpec[T]) MarshalYAML() (any, error) {
|
|
var v any
|
|
if o.Ref != nil {
|
|
v = o.Ref
|
|
} else {
|
|
v = o.Spec
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
// UnmarshalYAML implements yaml.Unmarshaler interface.
|
|
func (o *RefOrSpec[T]) UnmarshalYAML(node *yaml.Node) error {
|
|
if node.Decode(&o.Ref) == nil && o.Ref.Ref != "" {
|
|
return nil
|
|
}
|
|
|
|
o.Ref = nil
|
|
if err := node.Decode(&o.Spec); err != nil {
|
|
return fmt.Errorf("%T: %w", o.Spec, err)
|
|
}
|
|
return nil
|
|
}
|