git.iko.soy/typeable/swagger2
on master help sign in
Merge pull request #24 from GetShopTV/swagger-items

Introduce SwaggerItems GADT to simplify ParamSchema

commite1b45b12da065a9114bdb013eea9e23cb2cd8052 authorNickolay Kudasov <fizruk@users.noreply.github.com> dateSat 19 Dec 2015, 02:55 (11 years ago) parent0eb35c76d4d108
6 files changed+95−68
src/Data/Swagger.hs+1−1 src/Data/Swagger/Internal.hs+53−27 src/Data/Swagger/Internal/ParamSchema.hs+8−8 src/Data/Swagger/Internal/Schema.hs+6−6 src/Data/Swagger/Lens.hs+26−25 test/Data/Swagger/ParamSchemaSpec.hs+1−1
src/Data/Swagger.hs+1−1
@@ -45,7 +45,7 @@ module Data.Swagger (
4545 -- * Schemas
4646 ParamSchema(..),
4747 Schema(..),
48− SchemaItems(..),
48+ SwaggerItems(..),
4949 Xml(..),
5050
5151 -- * Responses
src/Data/Swagger/Internal.hs+53−27
@@ -10,6 +10,7 @@
1010{-# LANGUAGE ScopedTypeVariables #-}
1111{-# LANGUAGE StandaloneDeriving #-}
1212{-# LANGUAGE TemplateHaskell #-}
13+{-# LANGUAGE UndecidableInstances #-}
1314module Data.Swagger.Internal where
1415
1516import Control.Applicative
@@ -324,9 +325,33 @@ data ParamOtherSchema = ParamOtherSchema
324325 -- Default value is csv.
325326 , _paramOtherSchemaCollectionFormat :: Maybe (CollectionFormat Param)
326327
327− , _paramOtherSchemaParamSchema :: ParamSchema ParamOtherSchema Items
328+ , _paramOtherSchemaParamSchema :: ParamSchema ParamOtherSchema
328329 } deriving (Eq, Show, Generic, Data, Typeable)
329330
331+data SwaggerItems t where
332+ SwaggerItemsPrimitive :: Items -> SwaggerItems t
333+ SwaggerItemsObject :: Referenced Schema -> SwaggerItems Schema
334+ SwaggerItemsArray :: [Referenced Schema] -> SwaggerItems Schema
335+
336+deriving instance Eq (SwaggerItems t)
337+deriving instance Show (SwaggerItems t)
338+deriving instance Typeable (SwaggerItems t)
339+
340+swaggerItemsPrimitiveConstr :: Constr
341+swaggerItemsPrimitiveConstr = mkConstr swaggerItemsDataType "SwaggerItemsPrimitive" [] Prefix
342+
343+swaggerItemsDataType :: DataType
344+swaggerItemsDataType = mkDataType "Data.Swagger.SwaggerItems" [swaggerItemsPrimitiveConstr]
345+
346+instance {-# OVERLAPPABLE #-} Typeable t => Data (SwaggerItems t) where
347+ gunfold k z c = case constrIndex c of
348+ 1 -> k (z SwaggerItemsPrimitive)
349+ _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems t)."
350+ toConstr _ = swaggerItemsPrimitiveConstr
351+ dataTypeOf _ = swaggerItemsDataType
352+
353+deriving instance Data (SwaggerItems Schema)
354+
330355data SwaggerType t where
331356 SwaggerString :: SwaggerType t
332357 SwaggerNumber :: SwaggerType t
@@ -453,15 +478,10 @@ data Schema = Schema
453478 , _schemaMaxProperties :: Maybe Integer
454479 , _schemaMinProperties :: Maybe Integer
455480
456− , _schemaParamSchema :: ParamSchema Schema SchemaItems
481+ , _schemaParamSchema :: ParamSchema Schema
457482 } deriving (Eq, Show, Generic, Data, Typeable)
458483
459−data SchemaItems
460− = SchemaItemsObject (Referenced Schema)
461− | SchemaItemsArray [Referenced Schema]
462− deriving (Eq, Show, Generic, Data, Typeable)
463−
464−data ParamSchema t items = ParamSchema
484+data ParamSchema t = ParamSchema
465485 { -- | Declares the value of the parameter that the server will use if none is provided,
466486 -- for example a @"count"@ to control the number of results per page might default to @100@
467487 -- if not supplied by the client in the request.
@@ -471,7 +491,7 @@ data ParamSchema t items = ParamSchema
471491
472492 , _paramSchemaType :: SwaggerType t
473493 , _paramSchemaFormat :: Maybe Format
474− , _paramSchemaItems :: Maybe items
494+ , _paramSchemaItems :: Maybe (SwaggerItems t)
475495 , _paramSchemaMaximum :: Maybe Scientific
476496 , _paramSchemaExclusiveMaximum :: Maybe Bool
477497 , _paramSchemaMinimum :: Maybe Scientific
@@ -486,7 +506,7 @@ data ParamSchema t items = ParamSchema
486506 , _paramSchemaMultipleOf :: Maybe Scientific
487507 } deriving (Eq, Show, Generic, Typeable)
488508
489−deriving instance (Data t, Data (SwaggerType t), Data i) => Data (ParamSchema t i)
509+deriving instance (Data t, Data (SwaggerType t), Data (SwaggerItems t)) => Data (ParamSchema t)
490510
491511data Xml = Xml
492512 { -- | Replaces the name of the element/attribute used for the described schema property.
@@ -521,7 +541,7 @@ data Items = Items
521541 -- Default value is @'ItemsCollectionCSV'@.
522542 _itemsCollectionFormat :: Maybe (CollectionFormat Items)
523543
524− , _itemsParamSchema :: ParamSchema Items Items
544+ , _itemsParamSchema :: ParamSchema Items
525545 } deriving (Eq, Show, Generic, Data, Typeable)
526546
527547-- | A container for the expected responses of an operation.
@@ -571,7 +591,7 @@ data Header = Header
571591 -- Default value is @'ItemsCollectionCSV'@.
572592 , _headerCollectionFormat :: Maybe (CollectionFormat Items)
573593
574− , _headerParamSchema :: ParamSchema Header Items
594+ , _headerParamSchema :: ParamSchema Header
575595 } deriving (Eq, Show, Generic, Data, Typeable)
576596
577597data Example = Example { getExample :: Map MediaType Value }
@@ -706,7 +726,7 @@ instance Monoid Schema where
706726 mempty = genericMempty
707727 mappend = genericMappend
708728
709−instance Monoid (ParamSchema t i) where
729+instance Monoid (ParamSchema t) where
710730 mempty = genericMempty
711731 mappend = genericMappend
712732
@@ -742,7 +762,7 @@ instance SwaggerMonoid Info
742762instance SwaggerMonoid Paths
743763instance SwaggerMonoid PathItem
744764instance SwaggerMonoid Schema
745−instance SwaggerMonoid (ParamSchema t i)
765+instance SwaggerMonoid (ParamSchema t)
746766instance SwaggerMonoid Param
747767instance SwaggerMonoid ParamOtherSchema
748768instance SwaggerMonoid Responses
@@ -870,6 +890,11 @@ instance ToJSON Header where
870890instance ToJSON Items where
871891 toJSON = genericToJSONWithSub "paramSchema" (jsonPrefix "items")
872892
893+instance ToJSON (SwaggerItems t) where
894+ toJSON (SwaggerItemsPrimitive x) = toJSON x
895+ toJSON (SwaggerItemsObject x) = toJSON x
896+ toJSON (SwaggerItemsArray x) = toJSON x
897+
873898instance ToJSON Host where
874899 toJSON (Host host mport) = toJSON $
875900 case mport of
@@ -892,10 +917,6 @@ instance ToJSON ParamAnySchema where
892917instance ToJSON ParamOtherSchema where
893918 toJSON = genericToJSONWithSub "paramSchema" (jsonPrefix "paramOtherSchema")
894919
895−instance ToJSON SchemaItems where
896− toJSON (SchemaItemsObject x) = toJSON x
897− toJSON (SchemaItemsArray xs) = toJSON xs
898−
899920instance ToJSON Responses where
900921 toJSON (Responses def rs) = omitEmpties $
901922 toJSON (hashMapMapKeys show rs) <+> object [ "default" .= def ]
@@ -940,7 +961,7 @@ instance ToJSON (CollectionFormat t) where
940961 toJSON CollectionPipes = "pipes"
941962 toJSON CollectionMulti = "multi"
942963
943−instance ToJSON i => ToJSON (ParamSchema t i) where
964+instance ToJSON (ParamSchema t) where
944965 toJSON = genericToJSON (jsonPrefix "paramSchema")
945966
946967-- =======================================================================
@@ -1003,6 +1024,14 @@ instance FromJSON Header where
10031024instance FromJSON Items where
10041025 parseJSON = genericParseJSONWithSub "paramSchema" (jsonPrefix "items")
10051026
1027+instance {-# OVERLAPPABLE #-} FromJSON (SwaggerItems t) where
1028+ parseJSON js = SwaggerItemsPrimitive <$> parseJSON js
1029+
1030+instance {-# OVERLAPPING #-} FromJSON (SwaggerItems Schema) where
1031+ parseJSON js@(Object _) = SwaggerItemsObject <$> parseJSON js
1032+ parseJSON js@(Array _) = SwaggerItemsArray <$> parseJSON js
1033+ parseJSON _ = empty
1034+
10061035instance FromJSON Host where
10071036 parseJSON (String s) =
10081037 case fromInteger <$> readMaybe portStr of
@@ -1035,11 +1064,6 @@ instance FromJSON ParamAnySchema where
10351064instance FromJSON ParamOtherSchema where
10361065 parseJSON = genericParseJSONWithSub "paramSchema" (jsonPrefix "paramOtherSchema")
10371066
1038−instance FromJSON SchemaItems where
1039− parseJSON js@(Object _) = SchemaItemsObject <$> parseJSON js
1040− parseJSON js@(Array _) = SchemaItemsArray <$> parseJSON js
1041− parseJSON _ = empty
1042−
10431067instance FromJSON Responses where
10441068 parseJSON (Object o) = Responses
10451069 <$> o .:? "default"
@@ -1101,8 +1125,10 @@ instance FromJSON (CollectionFormat Param) where
11011125instance FromJSON (CollectionFormat Items) where
11021126 parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes]
11031127
1104−-- NOTE: The constraint @FromJSON (SwaggerType t)@ is necessary here!
1128+-- NOTE: The constraints @FromJSON (SwaggerType t)@ and
1129+-- @FromJSON (SwaggerItems t)@ are necessary here!
11051130-- Without the constraint the general instance will be used
1106−-- that only accepts common types (i.e. NOT object, null or file).
1107−instance (FromJSON (SwaggerType t), FromJSON i) => FromJSON (ParamSchema t i) where
1131+-- that only accepts common types (i.e. NOT object, null or file)
1132+-- and primitive array items.
1133+instance (FromJSON (SwaggerType t), FromJSON (SwaggerItems t)) => FromJSON (ParamSchema t) where
11081134 parseJSON = genericParseJSON (jsonPrefix "ParamSchema")
src/Data/Swagger/Internal/ParamSchema.hs+8−8
@@ -63,8 +63,8 @@ import Data.Swagger.SchemaOptions
6363-- @
6464class ToParamSchema a where
6565 -- | Convert a type into a plain parameter schema.
66− toParamSchema :: proxy a -> ParamSchema t i
67− default toParamSchema :: (Generic a, GToParamSchema (Rep a)) => proxy a -> ParamSchema t i
66+ toParamSchema :: proxy a -> ParamSchema t
67+ default toParamSchema :: (Generic a, GToParamSchema (Rep a)) => proxy a -> ParamSchema t
6868 toParamSchema = genericToParamSchema defaultSchemaOptions
6969
7070instance {-# OVERLAPPING #-} ToParamSchema String where
@@ -89,7 +89,7 @@ instance ToParamSchema Word32 where toParamSchema = toParamSchemaBoundedIntegral
8989instance ToParamSchema Word64 where toParamSchema = toParamSchemaBoundedIntegral
9090
9191-- | Default plain schema for @'Bounded'@, @'Integral'@ types.
92−toParamSchemaBoundedIntegral :: forall proxy a t i. (Bounded a, Integral a) => proxy a -> ParamSchema t i
92+toParamSchemaBoundedIntegral :: forall proxy a t. (Bounded a, Integral a) => proxy a -> ParamSchema t
9393toParamSchemaBoundedIntegral _ = mempty
9494 & schemaType .~ SwaggerInteger
9595 & schemaMinimum ?~ fromInteger (toInteger (minBound :: a))
@@ -110,7 +110,7 @@ instance ToParamSchema Double where
110110instance ToParamSchema Float where
111111 toParamSchema _ = mempty & schemaType .~ SwaggerNumber
112112
113−timeParamSchema :: String -> ParamSchema t i
113+timeParamSchema :: String -> ParamSchema t
114114timeParamSchema format = mempty
115115 & schemaType .~ SwaggerString
116116 & schemaFormat ?~ T.pack format
@@ -158,7 +158,7 @@ instance ToParamSchema a => ToParamSchema (Last a) where toParamSchema _ = to
158158instance ToParamSchema a => ToParamSchema (Dual a) where toParamSchema _ = toParamSchema (Proxy :: Proxy a)
159159
160160-- |
161−-- >>> encode (toParamSchema (Proxy :: Proxy ()) :: ParamSchema t Items)
161+-- >>> encode $ toParamSchema (Proxy :: Proxy ())
162162-- "{\"type\":\"string\",\"enum\":[\"_\"]}"
163163instance ToParamSchema () where
164164 toParamSchema _ = mempty
@@ -166,11 +166,11 @@ instance ToParamSchema () where
166166 & schemaEnum ?~ ["_"]
167167
168168-- | A configurable generic @'ParamSchema'@ creator.
169−genericToParamSchema :: forall proxy a t i. (Generic a, GToParamSchema (Rep a)) => SchemaOptions -> proxy a -> ParamSchema t i
169+genericToParamSchema :: forall proxy a t. (Generic a, GToParamSchema (Rep a)) => SchemaOptions -> proxy a -> ParamSchema t
170170genericToParamSchema opts _ = gtoParamSchema opts (Proxy :: Proxy (Rep a)) mempty
171171
172172class GToParamSchema (f :: * -> *) where
173− gtoParamSchema :: SchemaOptions -> proxy f -> ParamSchema t i -> ParamSchema t i
173+ gtoParamSchema :: SchemaOptions -> proxy f -> ParamSchema t -> ParamSchema t
174174
175175instance GToParamSchema f => GToParamSchema (D1 d f) where
176176 gtoParamSchema opts _ = gtoParamSchema opts (Proxy :: Proxy f)
@@ -185,7 +185,7 @@ instance (GEnumParamSchema f, GEnumParamSchema g) => GToParamSchema (f :+: g) wh
185185 gtoParamSchema opts _ = genumParamSchema opts (Proxy :: Proxy (f :+: g))
186186
187187class GEnumParamSchema (f :: * -> *) where
188− genumParamSchema :: SchemaOptions -> proxy f -> ParamSchema t i -> ParamSchema t i
188+ genumParamSchema :: SchemaOptions -> proxy f -> ParamSchema t -> ParamSchema t
189189
190190instance (GEnumParamSchema f, GEnumParamSchema g) => GEnumParamSchema (f :+: g) where
191191 genumParamSchema opts _ = genumParamSchema opts (Proxy :: Proxy f) . genumParamSchema opts (Proxy :: Proxy g)
src/Data/Swagger/Internal/Schema.hs+6−6
@@ -266,7 +266,7 @@ instance {-# OVERLAPPABLE #-} ToSchema a => ToSchema [a] where
266266 ref <- declareSchemaRef (Proxy :: Proxy a)
267267 return $ unnamed $ mempty
268268 & schemaType .~ SwaggerArray
269− & schemaItems ?~ SchemaItemsObject ref
269+ & schemaItems ?~ SwaggerItemsObject ref
270270
271271instance {-# OVERLAPPING #-} ToSchema String where declareNamedSchema = plain . paramSchemaToSchema
272272instance ToSchema Bool where declareNamedSchema = plain . paramSchemaToSchema
@@ -449,7 +449,7 @@ instance (Selector s, GToSchema f) => GToSchema (C1 c (S1 s f)) where
449449 | otherwise = do
450450 (_, schema) <- recordSchema
451451 case schema ^. schemaItems of
452− Just (SchemaItemsArray [_]) -> fieldSchema
452+ Just (SwaggerItemsArray [_]) -> fieldSchema
453453 _ -> pure (unnamed schema)
454454 where
455455 recordSchema = gdeclareNamedSchema opts (Proxy :: Proxy (S1 s f)) s
@@ -474,10 +474,10 @@ gdeclareSchemaRef opts proxy = do
474474 return $ Ref (Reference name)
475475 _ -> Inline <$> gdeclareSchema opts proxy
476476
477−appendItem :: Referenced Schema -> Maybe SchemaItems -> Maybe SchemaItems
478−appendItem x Nothing = Just (SchemaItemsArray [x])
479−appendItem x (Just (SchemaItemsArray xs)) = Just (SchemaItemsArray (x:xs))
480−appendItem _ _ = error "GToSchema.appendItem: cannot append to SchemaItemsObject"
477+appendItem :: Referenced Schema -> Maybe (SwaggerItems Schema) -> Maybe (SwaggerItems Schema)
478+appendItem x Nothing = Just (SwaggerItemsArray [x])
479+appendItem x (Just (SwaggerItemsArray xs)) = Just (SwaggerItemsArray (x:xs))
480+appendItem _ _ = error "GToSchema.appendItem: cannot append to SwaggerItemsObject"
481481
482482withFieldSchema :: forall proxy s f. (Selector s, GToSchema f) =>
483483 SchemaOptions -> proxy s f -> Bool -> Schema -> Declare Definitions Schema
src/Data/Swagger/Lens.hs+26−25
@@ -1,5 +1,6 @@
11{-# LANGUAGE FlexibleInstances #-}
22{-# LANGUAGE FunctionalDependencies #-}
3+{-# LANGUAGE GADTs #-}
34{-# LANGUAGE MultiParamTypeClasses #-}
45{-# LANGUAGE TemplateHaskell #-}
56module Data.Swagger.Lens where
@@ -43,8 +44,8 @@ makeLenses ''Items
4344makeLenses ''Header
4445-- ** 'Schema' lenses
4546makeLenses ''Schema
46−-- ** 'SchemaItems' prisms
47−makePrisms ''SchemaItems
47+-- ** 'SwaggerItems' prisms
48+makePrisms ''SwaggerItems
4849-- ** 'ParamSchema' lenses
4950makeLenses ''ParamSchema
5051-- ** 'Xml' lenses
@@ -80,60 +81,60 @@ instance HasDescription Schema (Maybe Text) where description = schemaDe
8081instance HasDescription SecurityScheme (Maybe Text) where description = securitySchemeDescription
8182instance HasDescription ExternalDocs (Maybe Text) where description = externalDocsDescription
8283
83−class HasParamSchema s t i | s -> t i where
84− parameterSchema :: Lens' s (ParamSchema t i)
84+class HasParamSchema s t | s -> t where
85+ parameterSchema :: Lens' s (ParamSchema t)
8586
86−instance HasParamSchema Schema Schema SchemaItems where parameterSchema = schemaParamSchema
87−instance HasParamSchema ParamOtherSchema ParamOtherSchema Items where parameterSchema = paramOtherSchemaParamSchema
88−instance HasParamSchema Items Items Items where parameterSchema = itemsParamSchema
89−instance HasParamSchema Header Header Items where parameterSchema = headerParamSchema
90−instance HasParamSchema (ParamSchema t i) t i where parameterSchema = id
87+instance HasParamSchema Schema Schema where parameterSchema = schemaParamSchema
88+instance HasParamSchema ParamOtherSchema ParamOtherSchema where parameterSchema = paramOtherSchemaParamSchema
89+instance HasParamSchema Items Items where parameterSchema = itemsParamSchema
90+instance HasParamSchema Header Header where parameterSchema = headerParamSchema
91+instance HasParamSchema (ParamSchema t) t where parameterSchema = id
9192
92−schemaType :: HasParamSchema s t i => Lens' s (SwaggerType t)
93+schemaType :: HasParamSchema s t => Lens' s (SwaggerType t)
9394schemaType = parameterSchema.paramSchemaType
9495
95−schemaFormat :: HasParamSchema s t i => Lens' s (Maybe Format)
96+schemaFormat :: HasParamSchema s t => Lens' s (Maybe Format)
9697schemaFormat = parameterSchema.paramSchemaFormat
9798
98−schemaItems :: HasParamSchema s t i => Lens' s (Maybe i)
99+schemaItems :: HasParamSchema s t => Lens' s (Maybe (SwaggerItems t))
99100schemaItems = parameterSchema.paramSchemaItems
100101
101−schemaDefault :: HasParamSchema s t i => Lens' s (Maybe Value)
102+schemaDefault :: HasParamSchema s t => Lens' s (Maybe Value)
102103schemaDefault = parameterSchema.paramSchemaDefault
103104
104−schemaMaximum :: HasParamSchema s t i => Lens' s (Maybe Scientific)
105+schemaMaximum :: HasParamSchema s t => Lens' s (Maybe Scientific)
105106schemaMaximum = parameterSchema.paramSchemaMaximum
106107
107−schemaExclusiveMaximum :: HasParamSchema s t i => Lens' s (Maybe Bool)
108+schemaExclusiveMaximum :: HasParamSchema s t => Lens' s (Maybe Bool)
108109schemaExclusiveMaximum = parameterSchema.paramSchemaExclusiveMaximum
109110
110−schemaMinimum :: HasParamSchema s t i => Lens' s (Maybe Scientific)
111+schemaMinimum :: HasParamSchema s t => Lens' s (Maybe Scientific)
111112schemaMinimum = parameterSchema.paramSchemaMinimum
112113
113−schemaExclusiveMinimum :: HasParamSchema s t i => Lens' s (Maybe Bool)
114+schemaExclusiveMinimum :: HasParamSchema s t => Lens' s (Maybe Bool)
114115schemaExclusiveMinimum = parameterSchema.paramSchemaExclusiveMinimum
115116
116−schemaMaxLength :: HasParamSchema s t i => Lens' s (Maybe Integer)
117+schemaMaxLength :: HasParamSchema s t => Lens' s (Maybe Integer)
117118schemaMaxLength = parameterSchema.paramSchemaMaxLength
118119
119−schemaMinLength :: HasParamSchema s t i => Lens' s (Maybe Integer)
120+schemaMinLength :: HasParamSchema s t => Lens' s (Maybe Integer)
120121schemaMinLength = parameterSchema.paramSchemaMinLength
121122
122−schemaPattern :: HasParamSchema s t i => Lens' s (Maybe Text)
123+schemaPattern :: HasParamSchema s t => Lens' s (Maybe Text)
123124schemaPattern = parameterSchema.paramSchemaPattern
124125
125−schemaMaxItems :: HasParamSchema s t i => Lens' s (Maybe Integer)
126+schemaMaxItems :: HasParamSchema s t => Lens' s (Maybe Integer)
126127schemaMaxItems = parameterSchema.paramSchemaMaxItems
127128
128−schemaMinItems :: HasParamSchema s t i => Lens' s (Maybe Integer)
129+schemaMinItems :: HasParamSchema s t => Lens' s (Maybe Integer)
129130schemaMinItems = parameterSchema.paramSchemaMinItems
130131
131−schemaUniqueItems :: HasParamSchema s t i => Lens' s (Maybe Bool)
132+schemaUniqueItems :: HasParamSchema s t => Lens' s (Maybe Bool)
132133schemaUniqueItems = parameterSchema.paramSchemaUniqueItems
133134
134−schemaEnum :: HasParamSchema s t i => Lens' s (Maybe [Value])
135+schemaEnum :: HasParamSchema s t => Lens' s (Maybe [Value])
135136schemaEnum = parameterSchema.paramSchemaEnum
136137
137−schemaMultipleOf :: HasParamSchema s t i => Lens' s (Maybe Scientific)
138+schemaMultipleOf :: HasParamSchema s t => Lens' s (Maybe Scientific)
138139schemaMultipleOf = parameterSchema.paramSchemaMultipleOf
139140
test/Data/Swagger/ParamSchemaSpec.hs+1−1
@@ -18,7 +18,7 @@ import SpecCommon
1818import Test.Hspec
1919
2020checkToParamSchema :: ToParamSchema a => Proxy a -> Value -> Spec
21−checkToParamSchema proxy js = (toParamSchema proxy :: ParamSchema Param Items) <=> js
21+checkToParamSchema proxy js = (toParamSchema proxy :: ParamSchema Param) <=> js
2222
2323spec :: Spec
2424spec = do