1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
package openapi3
import (
"context"
"encoding/json"
"fmt"
"sort"
)
// Encoding is specified by OpenAPI/Swagger 3.0 standard.
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#encoding-object
type Encoding struct {
Extensions map[string]interface{} `json:"-" yaml:"-"`
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
Style string `json:"style,omitempty" yaml:"style,omitempty"`
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
}
func NewEncoding() *Encoding {
return &Encoding{}
}
func (encoding *Encoding) WithHeader(name string, header *Header) *Encoding {
return encoding.WithHeaderRef(name, &HeaderRef{
Value: header,
})
}
func (encoding *Encoding) WithHeaderRef(name string, ref *HeaderRef) *Encoding {
headers := encoding.Headers
if headers == nil {
headers = make(map[string]*HeaderRef)
encoding.Headers = headers
}
headers[name] = ref
return encoding
}
// MarshalJSON returns the JSON encoding of Encoding.
func (encoding Encoding) MarshalJSON() ([]byte, error) {
m := make(map[string]interface{}, 5+len(encoding.Extensions))
for k, v := range encoding.Extensions {
m[k] = v
}
if x := encoding.ContentType; x != "" {
m["contentType"] = x
}
if x := encoding.Headers; len(x) != 0 {
m["headers"] = x
}
if x := encoding.Style; x != "" {
m["style"] = x
}
if x := encoding.Explode; x != nil {
m["explode"] = x
}
if x := encoding.AllowReserved; x {
m["allowReserved"] = x
}
return json.Marshal(m)
}
// UnmarshalJSON sets Encoding to a copy of data.
func (encoding *Encoding) UnmarshalJSON(data []byte) error {
type EncodingBis Encoding
var x EncodingBis
if err := json.Unmarshal(data, &x); err != nil {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, "contentType")
delete(x.Extensions, "headers")
delete(x.Extensions, "style")
delete(x.Extensions, "explode")
delete(x.Extensions, "allowReserved")
if len(x.Extensions) == 0 {
x.Extensions = nil
}
*encoding = Encoding(x)
return nil
}
// SerializationMethod returns a serialization method of request body.
// When serialization method is not defined the method returns the default serialization method.
func (encoding *Encoding) SerializationMethod() *SerializationMethod {
sm := &SerializationMethod{Style: SerializationForm, Explode: true}
if encoding != nil {
if encoding.Style != "" {
sm.Style = encoding.Style
}
if encoding.Explode != nil {
sm.Explode = *encoding.Explode
}
}
return sm
}
// Validate returns an error if Encoding does not comply with the OpenAPI spec.
func (encoding *Encoding) Validate(ctx context.Context, opts ...ValidationOption) error {
ctx = WithValidationOptions(ctx, opts...)
if encoding == nil {
return nil
}
headers := make([]string, 0, len(encoding.Headers))
for k := range encoding.Headers {
headers = append(headers, k)
}
sort.Strings(headers)
for _, k := range headers {
v := encoding.Headers[k]
if err := ValidateIdentifier(k); err != nil {
return nil
}
if err := v.Validate(ctx); err != nil {
return nil
}
}
// Validate a media types's serialization method.
sm := encoding.SerializationMethod()
switch {
case sm.Style == SerializationForm && sm.Explode,
sm.Style == SerializationForm && !sm.Explode,
sm.Style == SerializationSpaceDelimited && sm.Explode,
sm.Style == SerializationSpaceDelimited && !sm.Explode,
sm.Style == SerializationPipeDelimited && sm.Explode,
sm.Style == SerializationPipeDelimited && !sm.Explode,
sm.Style == SerializationDeepObject && sm.Explode:
default:
return fmt.Errorf("serialization method with style=%q and explode=%v is not supported by media type", sm.Style, sm.Explode)
}
return validateExtensions(ctx, encoding.Extensions)
}
|