blob: 4586a21c86023bfcebd04159db26856c41e3d856 [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001// 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
15package spec
16
17import (
18 "encoding/json"
19 "fmt"
20 "strconv"
21
22 "github.com/go-openapi/jsonpointer"
23 "github.com/go-openapi/swag"
24)
25
26// Swagger this is the root document object for the API specification.
27// It combines what previously was the Resource Listing and API Declaration (version 1.2 and earlier) together into one document.
28//
29// For more information: http://goo.gl/8us55a#swagger-object-
30type Swagger struct {
31 VendorExtensible
32 SwaggerProps
33}
34
35// JSONLookup look up a value by the json property name
36func (s Swagger) JSONLookup(token string) (interface{}, error) {
37 if ex, ok := s.Extensions[token]; ok {
38 return &ex, nil
39 }
40 r, _, err := jsonpointer.GetForToken(s.SwaggerProps, token)
41 return r, err
42}
43
44// MarshalJSON marshals this swagger structure to json
45func (s Swagger) MarshalJSON() ([]byte, error) {
46 b1, err := json.Marshal(s.SwaggerProps)
47 if err != nil {
48 return nil, err
49 }
50 b2, err := json.Marshal(s.VendorExtensible)
51 if err != nil {
52 return nil, err
53 }
54 return swag.ConcatJSON(b1, b2), nil
55}
56
57// UnmarshalJSON unmarshals a swagger spec from json
58func (s *Swagger) UnmarshalJSON(data []byte) error {
59 var sw Swagger
60 if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil {
61 return err
62 }
63 if err := json.Unmarshal(data, &sw.VendorExtensible); err != nil {
64 return err
65 }
66 *s = sw
67 return nil
68}
69
70// SwaggerProps captures the top-level properties of an Api specification
71type SwaggerProps struct {
72 ID string `json:"id,omitempty"`
73 Consumes []string `json:"consumes,omitempty"`
74 Produces []string `json:"produces,omitempty"`
75 Schemes []string `json:"schemes,omitempty"` // the scheme, when present must be from [http, https, ws, wss]
76 Swagger string `json:"swagger,omitempty"`
77 Info *Info `json:"info,omitempty"`
78 Host string `json:"host,omitempty"`
79 BasePath string `json:"basePath,omitempty"` // must start with a leading "/"
80 Paths *Paths `json:"paths"` // required
81 Definitions Definitions `json:"definitions,omitempty"`
82 Parameters map[string]Parameter `json:"parameters,omitempty"`
83 Responses map[string]Response `json:"responses,omitempty"`
84 SecurityDefinitions SecurityDefinitions `json:"securityDefinitions,omitempty"`
85 Security []map[string][]string `json:"security,omitempty"`
86 Tags []Tag `json:"tags,omitempty"`
87 ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
88}
89
90// Dependencies represent a dependencies property
91type Dependencies map[string]SchemaOrStringArray
92
93// SchemaOrBool represents a schema or boolean value, is biased towards true for the boolean property
94type SchemaOrBool struct {
95 Allows bool
96 Schema *Schema
97}
98
99// JSONLookup implements an interface to customize json pointer lookup
100func (s SchemaOrBool) JSONLookup(token string) (interface{}, error) {
101 if token == "allows" {
102 return s.Allows, nil
103 }
104 r, _, err := jsonpointer.GetForToken(s.Schema, token)
105 return r, err
106}
107
108var jsTrue = []byte("true")
109var jsFalse = []byte("false")
110
111// MarshalJSON convert this object to JSON
112func (s SchemaOrBool) MarshalJSON() ([]byte, error) {
113 if s.Schema != nil {
114 return json.Marshal(s.Schema)
115 }
116
117 if s.Schema == nil && !s.Allows {
118 return jsFalse, nil
119 }
120 return jsTrue, nil
121}
122
123// UnmarshalJSON converts this bool or schema object from a JSON structure
124func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
125 var nw SchemaOrBool
126 if len(data) >= 4 {
127 if data[0] == '{' {
128 var sch Schema
129 if err := json.Unmarshal(data, &sch); err != nil {
130 return err
131 }
132 nw.Schema = &sch
133 }
134 nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e')
135 }
136 *s = nw
137 return nil
138}
139
140// SchemaOrStringArray represents a schema or a string array
141type SchemaOrStringArray struct {
142 Schema *Schema
143 Property []string
144}
145
146// JSONLookup implements an interface to customize json pointer lookup
147func (s SchemaOrStringArray) JSONLookup(token string) (interface{}, error) {
148 r, _, err := jsonpointer.GetForToken(s.Schema, token)
149 return r, err
150}
151
152// MarshalJSON converts this schema object or array into JSON structure
153func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) {
154 if len(s.Property) > 0 {
155 return json.Marshal(s.Property)
156 }
157 if s.Schema != nil {
158 return json.Marshal(s.Schema)
159 }
160 return []byte("null"), nil
161}
162
163// UnmarshalJSON converts this schema object or array from a JSON structure
164func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error {
165 var first byte
166 if len(data) > 1 {
167 first = data[0]
168 }
169 var nw SchemaOrStringArray
170 if first == '{' {
171 var sch Schema
172 if err := json.Unmarshal(data, &sch); err != nil {
173 return err
174 }
175 nw.Schema = &sch
176 }
177 if first == '[' {
178 if err := json.Unmarshal(data, &nw.Property); err != nil {
179 return err
180 }
181 }
182 *s = nw
183 return nil
184}
185
186// Definitions contains the models explicitly defined in this spec
187// An object to hold data types that can be consumed and produced by operations.
188// These data types can be primitives, arrays or models.
189//
190// For more information: http://goo.gl/8us55a#definitionsObject
191type Definitions map[string]Schema
192
193// SecurityDefinitions a declaration of the security schemes available to be used in the specification.
194// This does not enforce the security schemes on the operations and only serves to provide
195// the relevant details for each scheme.
196//
197// For more information: http://goo.gl/8us55a#securityDefinitionsObject
198type SecurityDefinitions map[string]*SecurityScheme
199
200// StringOrArray represents a value that can either be a string
201// or an array of strings. Mainly here for serialization purposes
202type StringOrArray []string
203
204// Contains returns true when the value is contained in the slice
205func (s StringOrArray) Contains(value string) bool {
206 for _, str := range s {
207 if str == value {
208 return true
209 }
210 }
211 return false
212}
213
214// JSONLookup implements an interface to customize json pointer lookup
215func (s SchemaOrArray) JSONLookup(token string) (interface{}, error) {
216 if _, err := strconv.Atoi(token); err == nil {
217 r, _, err := jsonpointer.GetForToken(s.Schemas, token)
218 return r, err
219 }
220 r, _, err := jsonpointer.GetForToken(s.Schema, token)
221 return r, err
222}
223
224// UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string
225func (s *StringOrArray) UnmarshalJSON(data []byte) error {
226 var first byte
227 if len(data) > 1 {
228 first = data[0]
229 }
230
231 if first == '[' {
232 var parsed []string
233 if err := json.Unmarshal(data, &parsed); err != nil {
234 return err
235 }
236 *s = StringOrArray(parsed)
237 return nil
238 }
239
240 var single interface{}
241 if err := json.Unmarshal(data, &single); err != nil {
242 return err
243 }
244 if single == nil {
245 return nil
246 }
247 switch single.(type) {
248 case string:
249 *s = StringOrArray([]string{single.(string)})
250 return nil
251 default:
252 return fmt.Errorf("only string or array is allowed, not %T", single)
253 }
254}
255
256// MarshalJSON converts this string or array to a JSON array or JSON string
257func (s StringOrArray) MarshalJSON() ([]byte, error) {
258 if len(s) == 1 {
259 return json.Marshal([]string(s)[0])
260 }
261 return json.Marshal([]string(s))
262}
263
264// SchemaOrArray represents a value that can either be a Schema
265// or an array of Schema. Mainly here for serialization purposes
266type SchemaOrArray struct {
267 Schema *Schema
268 Schemas []Schema
269}
270
271// Len returns the number of schemas in this property
272func (s SchemaOrArray) Len() int {
273 if s.Schema != nil {
274 return 1
275 }
276 return len(s.Schemas)
277}
278
279// ContainsType returns true when one of the schemas is of the specified type
280func (s *SchemaOrArray) ContainsType(name string) bool {
281 if s.Schema != nil {
282 return s.Schema.Type != nil && s.Schema.Type.Contains(name)
283 }
284 return false
285}
286
287// MarshalJSON converts this schema object or array into JSON structure
288func (s SchemaOrArray) MarshalJSON() ([]byte, error) {
289 if len(s.Schemas) > 0 {
290 return json.Marshal(s.Schemas)
291 }
292 return json.Marshal(s.Schema)
293}
294
295// UnmarshalJSON converts this schema object or array from a JSON structure
296func (s *SchemaOrArray) UnmarshalJSON(data []byte) error {
297 var nw SchemaOrArray
298 var first byte
299 if len(data) > 1 {
300 first = data[0]
301 }
302 if first == '{' {
303 var sch Schema
304 if err := json.Unmarshal(data, &sch); err != nil {
305 return err
306 }
307 nw.Schema = &sch
308 }
309 if first == '[' {
310 if err := json.Unmarshal(data, &nw.Schemas); err != nil {
311 return err
312 }
313 }
314 *s = nw
315 return nil
316}
317
318// vim:set ft=go noet sts=2 sw=2 ts=2: