git.iko.soy/typeable/swagger2
on master help sign in
Merge pull request #5 from GetShopTV/refs

Support swagger references.

commit2d0e57a7ce3e1a35eb6efeb6e8afc2ebf65827b9 authorNickolay Kudasov <fizruk@users.noreply.github.com> dateTue 10 Nov 2015, 01:18 (11 years ago) parent18a081ecfa51ec
3 files changed+62−21
src/Data/Swagger.hs+4 src/Data/Swagger/Internal.hs+39−6 test/Data/SwaggerSpec.hs+19−15
src/Data/Swagger.hs+4
@@ -70,6 +70,10 @@ module Data.Swagger (
7070 -- * External documentation
7171 SwaggerExternalDocs(..),
7272
73+ -- * References
74+ SwaggerReference(..),
75+ SwaggerReferenced(..),
76+
7377 -- * Miscellaneous
7478 SwaggerMimeList(..),
7579 URL(..),
src/Data/Swagger/Internal.hs+39−6
@@ -189,7 +189,7 @@ data SwaggerPathItem = SwaggerPathItem
189189 -- These parameters can be overridden at the operation level, but cannot be removed there.
190190 -- The list MUST NOT include duplicated parameters.
191191 -- A unique parameter is defined by a combination of a name and location.
192− , swaggerPathItemParameters :: [SwaggerParameter]
192+ , swaggerPathItemParameters :: [SwaggerReferenced SwaggerParameter]
193193 } deriving (Eq, Show, Generic)
194194
195195-- | Describes a single API operation on a path.
@@ -230,7 +230,7 @@ data SwaggerOperation = SwaggerOperation
230230 -- the new definition will override it, but can never remove it.
231231 -- The list MUST NOT include duplicated parameters.
232232 -- A unique parameter is defined by a combination of a name and location.
233− , swaggerOperationParameters :: [SwaggerParameter]
233+ , swaggerOperationParameters :: [SwaggerReferenced SwaggerParameter]
234234
235235 -- | The list of possible responses as they are returned from executing this operation.
236236 , swaggerOperationResponses :: SwaggerResponses
@@ -392,7 +392,7 @@ data SwaggerSchema = SwaggerSchema
392392
393393 , swaggerSchemaItems :: Maybe SwaggerSchemaItems
394394 , swaggerSchemaAllOf :: Maybe [SwaggerSchema]
395− , swaggerSchemaProperties :: HashMap Text SwaggerSchema
395+ , swaggerSchemaProperties :: HashMap Text (SwaggerReferenced SwaggerSchema)
396396 , swaggerSchemaAdditionalProperties :: Maybe SwaggerSchema
397397
398398 , swaggerSchemaDiscriminator :: Maybe Text
@@ -488,11 +488,11 @@ data SwaggerItems = SwaggerItems
488488data SwaggerResponses = SwaggerResponses
489489 { -- | The documentation of responses other than the ones declared for specific HTTP response codes.
490490 -- It can be used to cover undeclared responses.
491− swaggerResponsesDefault :: Maybe SwaggerResponse
491+ swaggerResponsesDefault :: Maybe (SwaggerReferenced SwaggerResponse)
492492
493493 -- | Any HTTP status code can be used as the property name (one property per HTTP status code).
494494 -- Describes the expected response for those HTTP status codes.
495− , swaggerResponsesResponses :: HashMap HttpStatusCode SwaggerResponse
495+ , swaggerResponsesResponses :: HashMap HttpStatusCode (SwaggerReferenced SwaggerResponse)
496496 } deriving (Eq, Show, Generic)
497497
498498type HttpStatusCode = Int
@@ -623,6 +623,16 @@ data SwaggerExternalDocs = SwaggerExternalDocs
623623 , swaggerExternalDocsUrl :: URL
624624 } deriving (Eq, Show, Generic)
625625
626+-- | A simple object to allow referencing other definitions in the specification.
627+-- It can be used to reference parameters and responses that are defined at the top level for reuse.
628+newtype SwaggerReference = SwaggerReference { getSwaggerReference :: Text }
629+ deriving (Eq, Show)
630+
631+data SwaggerReferenced a
632+ = SwaggerRef SwaggerReference
633+ | SwaggerInline a
634+ deriving (Eq, Show)
635+
626636newtype URL = URL { getUrl :: Text } deriving (Eq, Show, ToJSON, FromJSON)
627637
628638-- =======================================================================
@@ -712,6 +722,13 @@ instance SwaggerMonoid (HashMap Text SwaggerSchema) where
712722 swaggerMempty = HashMap.empty
713723 swaggerMappend = HashMap.unionWith mappend
714724
725+instance SwaggerMonoid (HashMap Text (SwaggerReferenced SwaggerSchema)) where
726+ swaggerMempty = HashMap.empty
727+ swaggerMappend = HashMap.unionWith merge
728+ where
729+ merge (SwaggerInline x) (SwaggerInline y) = SwaggerInline (x <> y)
730+ merge _ y = y
731+
715732instance SwaggerMonoid (HashMap Text SwaggerParameter) where
716733 swaggerMempty = HashMap.empty
717734 swaggerMappend = HashMap.unionWith mappend
@@ -732,7 +749,7 @@ instance SwaggerMonoid (HashMap HeaderName SwaggerHeader) where
732749 swaggerMempty = HashMap.empty
733750 swaggerMappend = flip HashMap.union
734751
735−instance SwaggerMonoid (HashMap HttpStatusCode SwaggerResponse) where
752+instance SwaggerMonoid (HashMap HttpStatusCode (SwaggerReferenced SwaggerResponse)) where
736753 swaggerMempty = HashMap.empty
737754 swaggerMappend = flip HashMap.union
738755
@@ -849,6 +866,13 @@ instance ToJSON SwaggerResponses where
849866instance ToJSON SwaggerExample where
850867 toJSON = toJSON . Map.mapKeys show . getSwaggerExample
851868
869+instance ToJSON SwaggerReference where
870+ toJSON (SwaggerReference ref) = object [ "$ref" .= ref ]
871+
872+instance ToJSON a => ToJSON (SwaggerReferenced a) where
873+ toJSON (SwaggerRef ref) = toJSON ref
874+ toJSON (SwaggerInline x) = toJSON x
875+
852876-- =======================================================================
853877-- Manual FromJSON instances
854878-- =======================================================================
@@ -970,3 +994,12 @@ instance FromJSON SwaggerPathItem where
970994 parseJSON = genericParseJSON (jsonPrefix "swaggerPathItem")
971995 `withDefaults` [ "parameters" .= ([] :: [SwaggerParameter]) ]
972996
997+instance FromJSON SwaggerReference where
998+ parseJSON (Object o) = SwaggerReference <$> o .: "$ref"
999+ parseJSON _ = empty
1000+
1001+instance FromJSON a => FromJSON (SwaggerReferenced a) where
1002+ parseJSON json
1003+ = SwaggerRef <$> parseJSON json
1004+ <|> SwaggerInline <$> parseJSON json
1005+
test/Data/SwaggerSpec.hs+19−15
@@ -153,10 +153,10 @@ operationExample = mempty
153153
154154 responses = mempty
155155 { swaggerResponsesResponses =
156− [ (200, mempty { swaggerResponseDescription = "Pet updated." })
157− , (405, mempty { swaggerResponseDescription = "Invalid input" }) ] }
156+ [ (200, SwaggerInline mempty { swaggerResponseDescription = "Pet updated." })
157+ , (405, SwaggerInline mempty { swaggerResponseDescription = "Invalid input" }) ] }
158158
159− params =
159+ params = map SwaggerInline
160160 [ SwaggerParameter
161161 { swaggerParameterName = "petId"
162162 , swaggerParameterDescription = Just "ID of pet that needs to be updated"
@@ -260,9 +260,10 @@ schemaSimpleModelExample = mempty
260260 { swaggerSchemaType = SwaggerSchemaObject
261261 , swaggerSchemaRequired = [ "name" ]
262262 , swaggerSchemaProperties =
263− [ ("name", mempty
263+ [ ("name", SwaggerInline mempty
264264 { swaggerSchemaType = SwaggerSchemaString } )
265− , ("age", mempty
265+ , ("address", SwaggerRef (SwaggerReference "#/definitions/Address"))
266+ , ("age", SwaggerInline mempty
266267 { swaggerSchemaType = SwaggerSchemaInteger
267268 , swaggerSchemaFormat = Just "int32"
268269 , swaggerSchemaCommon = mempty
@@ -279,6 +280,9 @@ schemaSimpleModelExampleJSON = [aesonQQ|
279280 "name": {
280281 "type": "string"
281282 },
283+ "address": {
284+ "$ref": "#/definitions/Address"
285+ },
282286 "age": {
283287 "type": "integer",
284288 "format": "int32",
@@ -308,10 +312,10 @@ schemaWithExampleExample :: SwaggerSchema
308312schemaWithExampleExample = mempty
309313 { swaggerSchemaType = SwaggerSchemaObject
310314 , swaggerSchemaProperties =
311− [ ("id", mempty
315+ [ ("id", SwaggerInline mempty
312316 { swaggerSchemaType = SwaggerSchemaInteger
313317 , swaggerSchemaFormat = Just "int64" })
314− , ("name", mempty
318+ , ("name", SwaggerInline mempty
315319 { swaggerSchemaType = SwaggerSchemaString }) ]
316320 , swaggerSchemaRequired = [ "name" ]
317321 , swaggerSchemaExample = Just [aesonQQ|
@@ -353,18 +357,18 @@ definitionsExample =
353357 [ ("Category", mempty
354358 { swaggerSchemaType = SwaggerSchemaObject
355359 , swaggerSchemaProperties =
356− [ ("id", mempty
360+ [ ("id", SwaggerInline mempty
357361 { swaggerSchemaType = SwaggerSchemaInteger
358362 , swaggerSchemaFormat = Just "int64" })
359− , ("name", mempty
363+ , ("name", SwaggerInline mempty
360364 { swaggerSchemaType = SwaggerSchemaString }) ] })
361365 , ("Tag", mempty
362366 { swaggerSchemaType = SwaggerSchemaObject
363367 , swaggerSchemaProperties =
364− [ ("id", mempty
368+ [ ("id", SwaggerInline mempty
365369 { swaggerSchemaType = SwaggerSchemaInteger
366370 , swaggerSchemaFormat = Just "int64" })
367− , ("name", mempty
371+ , ("name", SwaggerInline mempty
368372 { swaggerSchemaType = SwaggerSchemaString }) ] }) ]
369373
370374definitionsExampleJSON :: Value
@@ -521,7 +525,7 @@ swaggerExample = mempty
521525 { swaggerPathItemGet = Just mempty
522526 { swaggerOperationResponses = mempty
523527 { swaggerResponsesResponses =
524− [ (200, mempty
528+ [ (200, SwaggerInline mempty
525529 { swaggerResponseSchema = Just mempty
526530 { swaggerSchemaExample = Just [aesonQQ|
527531 {
@@ -531,15 +535,15 @@ swaggerExample = mempty
531535 , swaggerSchemaType = SwaggerSchemaObject
532536 , swaggerSchemaDescription = Just "This is some real Todo right here"
533537 , swaggerSchemaProperties =
534− [ ("created", mempty
538+ [ ("created", SwaggerInline mempty
535539 { swaggerSchemaType = SwaggerSchemaInteger
536540 , swaggerSchemaFormat = Just "int32" })
537− , ("description", mempty
541+ , ("description", SwaggerInline mempty
538542 { swaggerSchemaType = SwaggerSchemaString }) ] }
539543 , swaggerResponseDescription = "OK" }) ] }
540544 , swaggerOperationProduces = Just (SwaggerMimeList [ "application/json" ])
541545 , swaggerOperationParameters =
542− [ mempty
546+ [ SwaggerInline mempty
543547 { swaggerParameterRequired = True
544548 , swaggerParameterName = "id"
545549 , swaggerParameterDescription = Just "TodoId param"