k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/validation/spec/info.go (about) 1 // Copyright 2015 go-swagger maintainers 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package spec 16 17 import ( 18 "encoding/json" 19 "strings" 20 21 "github.com/go-openapi/swag" 22 "k8s.io/kube-openapi/pkg/internal" 23 jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" 24 ) 25 26 // Extensions vendor specific extensions 27 type Extensions map[string]interface{} 28 29 // Add adds a value to these extensions 30 func (e Extensions) Add(key string, value interface{}) { 31 realKey := strings.ToLower(key) 32 e[realKey] = value 33 } 34 35 // GetString gets a string value from the extensions 36 func (e Extensions) GetString(key string) (string, bool) { 37 if v, ok := e[strings.ToLower(key)]; ok { 38 str, ok := v.(string) 39 return str, ok 40 } 41 return "", false 42 } 43 44 // GetBool gets a string value from the extensions 45 func (e Extensions) GetBool(key string) (bool, bool) { 46 if v, ok := e[strings.ToLower(key)]; ok { 47 str, ok := v.(bool) 48 return str, ok 49 } 50 return false, false 51 } 52 53 // GetStringSlice gets a string value from the extensions 54 func (e Extensions) GetStringSlice(key string) ([]string, bool) { 55 if v, ok := e[strings.ToLower(key)]; ok { 56 arr, isSlice := v.([]interface{}) 57 if !isSlice { 58 return nil, false 59 } 60 var strs []string 61 for _, iface := range arr { 62 str, isString := iface.(string) 63 if !isString { 64 return nil, false 65 } 66 strs = append(strs, str) 67 } 68 return strs, ok 69 } 70 return nil, false 71 } 72 73 // GetObject gets the object value from the extensions. 74 // out must be a json serializable type; the json go struct 75 // tags of out are used to populate it. 76 func (e Extensions) GetObject(key string, out interface{}) error { 77 // This json serialization/deserialization could be replaced with 78 // an approach using reflection if the optimization becomes justified. 79 if v, ok := e[strings.ToLower(key)]; ok { 80 b, err := json.Marshal(v) 81 if err != nil { 82 return err 83 } 84 err = json.Unmarshal(b, out) 85 if err != nil { 86 return err 87 } 88 } 89 return nil 90 } 91 92 func (e Extensions) sanitizeWithExtra() (extra map[string]any) { 93 for k, v := range e { 94 if !internal.IsExtensionKey(k) { 95 if extra == nil { 96 extra = make(map[string]any) 97 } 98 extra[k] = v 99 delete(e, k) 100 } 101 } 102 return extra 103 } 104 105 // VendorExtensible composition block. 106 type VendorExtensible struct { 107 Extensions Extensions 108 } 109 110 // AddExtension adds an extension to this extensible object 111 func (v *VendorExtensible) AddExtension(key string, value interface{}) { 112 if value == nil { 113 return 114 } 115 if v.Extensions == nil { 116 v.Extensions = make(map[string]interface{}) 117 } 118 v.Extensions.Add(key, value) 119 } 120 121 // MarshalJSON marshals the extensions to json 122 func (v VendorExtensible) MarshalJSON() ([]byte, error) { 123 toser := make(map[string]interface{}) 124 for k, v := range v.Extensions { 125 lk := strings.ToLower(k) 126 if strings.HasPrefix(lk, "x-") { 127 toser[k] = v 128 } 129 } 130 return json.Marshal(toser) 131 } 132 133 // UnmarshalJSON for this extensible object 134 func (v *VendorExtensible) UnmarshalJSON(data []byte) error { 135 var d map[string]interface{} 136 if err := json.Unmarshal(data, &d); err != nil { 137 return err 138 } 139 for k, vv := range d { 140 lk := strings.ToLower(k) 141 if strings.HasPrefix(lk, "x-") { 142 if v.Extensions == nil { 143 v.Extensions = map[string]interface{}{} 144 } 145 v.Extensions[k] = vv 146 } 147 } 148 return nil 149 } 150 151 // InfoProps the properties for an info definition 152 type InfoProps struct { 153 Description string `json:"description,omitempty"` 154 Title string `json:"title,omitempty"` 155 TermsOfService string `json:"termsOfService,omitempty"` 156 Contact *ContactInfo `json:"contact,omitempty"` 157 License *License `json:"license,omitempty"` 158 Version string `json:"version,omitempty"` 159 } 160 161 // Info object provides metadata about the API. 162 // The metadata can be used by the clients if needed, and can be presented in the Swagger-UI for convenience. 163 // 164 // For more information: http://goo.gl/8us55a#infoObject 165 type Info struct { 166 VendorExtensible 167 InfoProps 168 } 169 170 // MarshalJSON marshal this to JSON 171 func (i Info) MarshalJSON() ([]byte, error) { 172 if internal.UseOptimizedJSONMarshaling { 173 return internal.DeterministicMarshal(i) 174 } 175 b1, err := json.Marshal(i.InfoProps) 176 if err != nil { 177 return nil, err 178 } 179 b2, err := json.Marshal(i.VendorExtensible) 180 if err != nil { 181 return nil, err 182 } 183 return swag.ConcatJSON(b1, b2), nil 184 } 185 186 func (i Info) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { 187 var x struct { 188 Extensions 189 InfoProps 190 } 191 x.Extensions = i.Extensions 192 x.InfoProps = i.InfoProps 193 return opts.MarshalNext(enc, x) 194 } 195 196 // UnmarshalJSON marshal this from JSON 197 func (i *Info) UnmarshalJSON(data []byte) error { 198 if internal.UseOptimizedJSONUnmarshaling { 199 return jsonv2.Unmarshal(data, i) 200 } 201 202 if err := json.Unmarshal(data, &i.InfoProps); err != nil { 203 return err 204 } 205 return json.Unmarshal(data, &i.VendorExtensible) 206 } 207 208 func (i *Info) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { 209 var x struct { 210 Extensions 211 InfoProps 212 } 213 if err := opts.UnmarshalNext(dec, &x); err != nil { 214 return err 215 } 216 i.Extensions = internal.SanitizeExtensions(x.Extensions) 217 i.InfoProps = x.InfoProps 218 return nil 219 }