@@ -1,6 +1,6 @@
1−{-# LANGUAGE CPP #-}
21{-# LANGUAGE DataKinds #-}
32{-# LANGUAGE DeriveDataTypeable #-}
3+{-# LANGUAGE DeriveFunctor #-}
44{-# LANGUAGE DeriveGeneric #-}
55{-# LANGUAGE DeriveTraversable #-}
66{-# LANGUAGE FlexibleContexts #-}
@@ -14,91 +14,87 @@
1414{-# LANGUAGE TemplateHaskell #-}
1515{-# LANGUAGE TypeFamilies #-}
1616{-# LANGUAGE UndecidableInstances #-}
17−module Data.OpenApi.Internal where
17+module Data.Swagger.Internal where
1818
1919import Prelude ()
2020import Prelude.Compat
2121
22+import Control.Lens ((&), (.~), (?~))
2223import Control.Applicative
23−import Control.Lens ((&), (.~), (?~))
24−import Data.Aeson hiding (Encoding)
25−#if MIN_VERSION_aeson(2,0,0)
26−import qualified Data.Aeson.KeyMap as KeyMap
27−#endif
28−import qualified Data.Aeson.Types as JSON
29−import Data.Data (Constr, Data (..), DataType, Fixity (..), Typeable,
30− constrIndex, mkConstr, mkDataType)
31−import Data.Hashable (Hashable (..))
32−import qualified Data.HashMap.Strict as HashMap
33−import Data.HashSet.InsOrd (InsOrdHashSet)
34−import Data.Map (Map)
35−import qualified Data.Map as Map
36−import Data.Monoid (Monoid (..))
37−import Data.Scientific (Scientific)
38−import Data.Semigroup.Compat (Semigroup (..))
39−import Data.String (IsString (..))
40−import Data.Text (Text)
41−import qualified Data.Text as Text
42−import Data.Text.Encoding (encodeUtf8)
43−import GHC.Generics (Generic)
44−import Network.HTTP.Media (MediaType, mainType, parameters, parseAccept, subType, (//),
45− (/:))
46−import Network.Socket (HostName, PortNumber)
47−import Text.Read (readMaybe)
24+import Data.Aeson hiding (Encoding)
25+import qualified Data.Aeson.Types as JSON
26+import Data.Data (Data(..), Typeable, mkConstr, mkDataType, Fixity(..), Constr, DataType, constrIndex)
27+import Data.Hashable (Hashable)
28+import qualified Data.HashMap.Strict as HashMap
29+import Data.HashSet.InsOrd (InsOrdHashSet)
30+import Data.Map (Map)
31+import qualified Data.Map as Map
32+import Data.Monoid (Monoid (..))
33+import Data.Semigroup.Compat (Semigroup (..))
34+import Data.Scientific (Scientific)
35+import Data.String (IsString(..))
36+import Data.Text (Text)
37+import qualified Data.Text as Text
38+import GHC.Generics (Generic)
39+import Network.Socket (HostName, PortNumber)
40+import Network.HTTP.Media (MediaType)
41+import Text.Read (readMaybe)
4842
4943import Data.HashMap.Strict.InsOrd (InsOrdHashMap)
5044import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
5145
52−import Data.OpenApi.Aeson.Compat (deleteKey)
53−import Data.OpenApi.Internal.AesonUtils (AesonDefaultValue (..), HasSwaggerAesonOptions (..),
54− mkSwaggerAesonOptions, saoAdditionalPairs, saoSubObject,
55− sopSwaggerGenericParseJSON, sopSwaggerGenericToEncoding,
56− sopSwaggerGenericToJSON, sopSwaggerGenericToJSONWithOpts)
57−import Data.OpenApi.Internal.Utils
5846import Generics.SOP.TH (deriveGeneric)
47+import Data.Swagger.Internal.AesonUtils (sopSwaggerGenericToJSON
48+ ,sopSwaggerGenericToJSONWithOpts
49+ ,sopSwaggerGenericParseJSON
50+ ,HasSwaggerAesonOptions(..)
51+ ,AesonDefaultValue(..)
52+ ,mkSwaggerAesonOptions
53+ ,saoAdditionalPairs
54+ ,saoSubObject)
55+import Data.Swagger.Internal.Utils
56+import Data.Swagger.Internal.AesonUtils (sopSwaggerGenericToEncoding)
5957
6058-- $setup
6159-- >>> :seti -XDataKinds
6260-- >>> import Data.Aeson
63−-- >>> import Data.ByteString.Lazy.Char8 as BSL
64−-- >>> import Data.OpenApi.Internal.Utils
6561
6662-- | A list of definitions that can be used in references.
6763type Definitions = InsOrdHashMap Text
6864
6965-- | This is the root document object for the API specification.
70−data OpenApi = OpenApi
66+data Swagger = Swagger
7167 { -- | Provides metadata about the API.
7268 -- The metadata can be used by the clients if needed.
73− _openApiInfo :: Info
69+ _swaggerInfo :: Info
7470
7571 -- | An array of Server Objects, which provide connectivity information
7672 -- to a target server. If the servers property is not provided, or is an empty array,
7773 -- the default value would be a 'Server' object with a url value of @/@.
78− , _openApiServers :: [Server]
74+ , _swaggerServers :: [Server]
7975
8076 -- | The available paths and operations for the API.
81− , _openApiPaths :: InsOrdHashMap FilePath PathItem
77+ , _swaggerPaths :: InsOrdHashMap FilePath PathItem
8278
8379 -- | An element to hold various schemas for the specification.
84− , _openApiComponents :: Components
80+ , _swaggerComponents :: Components
8581
8682 -- | A declaration of which security mechanisms can be used across the API.
8783 -- The list of values includes alternative security requirement objects that can be used.
8884 -- Only one of the security requirement objects need to be satisfied to authorize a request.
8985 -- Individual operations can override this definition.
9086 -- To make security optional, an empty security requirement can be included in the array.
91− , _openApiSecurity :: [SecurityRequirement]
87+ , _swaggerSecurity :: [SecurityRequirement]
9288
9389 -- | A list of tags used by the specification with additional metadata.
9490 -- The order of the tags can be used to reflect on their order by the parsing tools.
9591 -- Not all tags that are used by the 'Operation' Object must be declared.
9692 -- The tags that are not declared MAY be organized randomly or based on the tools' logic.
9793 -- Each tag name in the list MUST be unique.
98− , _openApiTags :: InsOrdHashSet Tag
94+ , _swaggerTags :: InsOrdHashSet Tag
9995
10096 -- | Additional external documentation.
101− , _openApiExternalDocs :: Maybe ExternalDocs
97+ , _swaggerExternalDocs :: Maybe ExternalDocs
10298 } deriving (Eq, Show, Generic, Data, Typeable)
10399
104100-- | The object provides metadata about the API.
@@ -195,10 +191,10 @@ data Components = Components
195191 , _componentsParameters :: Definitions Param
196192 , _componentsExamples :: Definitions Example
197193 , _componentsRequestBodies :: Definitions RequestBody
198− , _componentsHeaders :: Definitions Header
199− , _componentsSecuritySchemes :: SecurityDefinitions
200− , _componentsLinks :: Definitions Link
201− , _componentsCallbacks :: Definitions Callback
194+ , _componentsHeader :: Definitions Header
195+ , _componentsSecuritySchemes :: Definitions SecurityScheme
196+-- , _componentsLinks
197+-- , _componentsCallbacks
202198 } deriving (Eq, Show, Generic, Data, Typeable)
203199
204200-- | Describes the operations available on a single path.
@@ -288,11 +284,7 @@ data Operation = Operation
288284 -- | The list of possible responses as they are returned from executing this operation.
289285 , _operationResponses :: Responses
290286
291− -- | A map of possible out-of band callbacks related to the parent operation.
292− -- The key is a unique identifier for the 'Callback' Object.
293− -- Each value in the map is a 'Callback' Object that describes a request
294− -- that may be initiated by the API provider and the expected responses.
295− , _operationCallbacks :: InsOrdHashMap Text (Referenced Callback)
287+ -- TODO callbacks
296288
297289 -- | Declares this operation to be deprecated.
298290 -- Usage of the declared operation should be refrained.
@@ -312,22 +304,6 @@ data Operation = Operation
312304 , _operationServers :: [Server]
313305 } deriving (Eq, Show, Generic, Data, Typeable)
314306
315−-- This instance should be in @http-media@.
316−instance Data MediaType where
317− gunfold k z c = case constrIndex c of
318− 1 -> k (k (k (z (\main sub params -> foldl (/:) (main // sub) (Map.toList params)))))
319− _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type MediaType."
320−
321− toConstr _ = mediaTypeConstr
322−
323− dataTypeOf _ = mediaTypeData
324−
325−mediaTypeConstr = mkConstr mediaTypeData "MediaType" [] Prefix
326−mediaTypeData = mkDataType "MediaType" [mediaTypeConstr]
327−
328−instance Hashable MediaType where
329− hashWithSalt salt mt = salt `hashWithSalt` show mt
330−
331307-- | Describes a single request body.
332308data RequestBody = RequestBody
333309 { -- | A brief description of the request body. This could contain examples of use.
@@ -337,11 +313,9 @@ data RequestBody = RequestBody
337313 -- | The content of the request body.
338314 -- The key is a media type or media type range and the value describes it.
339315 -- For requests that match multiple keys, only the most specific key is applicable.
340− -- e.g. @text/plain@ overrides @text/\*@
341− , _requestBodyContent :: InsOrdHashMap MediaType MediaTypeObject
316+ -- e.g. @text/plain@ overrides @text/*@
317+ , _requestBodyContent :: InsOrdHashMap {-MediaType-} Text MediaTypeObject -- FIXME Data MediaType
342318
343− -- | Determines if the request body is required in the request.
344− -- Defaults to 'False'.
345319 , _requestBodyRequired :: Maybe Bool
346320 } deriving (Eq, Show, Generic, Data, Typeable)
347321
@@ -364,29 +338,6 @@ data MediaTypeObject = MediaTypeObject
364338 , _mediaTypeObjectEncoding :: InsOrdHashMap Text Encoding
365339 } deriving (Eq, Show, Generic, Data, Typeable)
366340
367−-- | In order to support common ways of serializing simple parameters, a set of style values are defined.
368−data Style
369− = StyleMatrix
370− -- ^ Path-style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
371− | StyleLabel
372− -- ^ Label style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
373− | StyleForm
374− -- ^ Form style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
375− -- This option replaces @collectionFormat@ with a @csv@ (when @explode@ is false) or @multi@
376− -- (when explode is true) value from OpenAPI 2.0.
377− | StyleSimple
378− -- ^ Simple style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
379− -- This option replaces @collectionFormat@ with a @csv@ value from OpenAPI 2.0.
380− | StyleSpaceDelimited
381− -- ^ Space separated array values.
382− -- This option replaces @collectionFormat@ equal to @ssv@ from OpenAPI 2.0.
383− | StylePipeDelimited
384− -- ^ Pipe separated array values.
385− -- This option replaces @collectionFormat@ equal to @pipes@ from OpenAPI 2.0.
386− | StyleDeepObject
387− -- ^ Provides a simple way of rendering nested objects using form parameters.
388− deriving (Eq, Show, Generic, Data, Typeable)
389−
390341data Encoding = Encoding
391342 { -- | The Content-Type for encoding a specific property.
392343 -- Default value depends on the property type: for @string@
@@ -394,8 +345,8 @@ data Encoding = Encoding
394345 -- for other primitive types – @text/plain@; for object - @application/json@;
395346 -- for array – the default is defined based on the inner type.
396347 -- The value can be a specific media type (e.g. @application/json@),
397− -- a wildcard media type (e.g. @image/\*@), or a comma-separated list of the two types.
398− _encodingContentType :: Maybe MediaType
348+ -- a wildcard media type (e.g. @image/*@), or a comma-separated list of the two types.
349+ _encodingContentType :: Maybe Text
399350
400351 -- | A map allowing additional information to be provided as headers,
401352 -- for example @Content-Disposition@. @Content-Type@ is described separately
@@ -404,11 +355,11 @@ data Encoding = Encoding
404355 , _encodingHeaders :: InsOrdHashMap Text (Referenced Header)
405356
406357 -- | Describes how a specific property value will be serialized depending on its type.
407− -- See 'Param' Object for details on the style property.
358+ -- See Parameter Object for details on the style property.
408359 -- The behavior follows the same values as query parameters, including default values.
409360 -- This property SHALL be ignored if the request body media type
410361 -- is not @application/x-www-form-urlencoded@.
411− , _encodingStyle :: Maybe Style
362+ , _encodingStyle :: Maybe Text -- TODO enum
412363
413364 -- | When this is true, property values of type @array@ or @object@ generate
414365 -- separate parameters for each value of the array,
@@ -434,15 +385,18 @@ mimeListConstr :: Constr
434385mimeListConstr = mkConstr mimeListDataType "MimeList" ["getMimeList"] Prefix
435386
436387mimeListDataType :: DataType
437−mimeListDataType = mkDataType "Data.OpenApi.MimeList" [mimeListConstr]
388+mimeListDataType = mkDataType "Data.Swagger.MimeList" [mimeListConstr]
438389
439390instance Data MimeList where
440391 gunfold k z c = case constrIndex c of
441− 1 -> k (z (MimeList . map fromString))
392+ 1 -> k (z (\xs -> MimeList (map fromString xs)))
442393 _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type MimeList."
443394 toConstr (MimeList _) = mimeListConstr
444395 dataTypeOf _ = mimeListDataType
445396
397+-- TODO style
398+-- TODO example
399+
446400-- | Describes a single operation parameter.
447401-- A unique parameter is defined by a combination of a name and location.
448402data Param = Param
@@ -452,7 +406,7 @@ data Param = Param
452406
453407 -- | A brief description of the parameter.
454408 -- This could contain examples of use.
455− -- CommonMark syntax MAY be used for rich text representation.
409+ -- GFM syntax can be used for rich text representation.
456410 , _paramDescription :: Maybe Text
457411
458412 -- | Determines whether this parameter is mandatory.
@@ -470,49 +424,10 @@ data Param = Param
470424 -- | Sets the ability to pass empty-valued parameters.
471425 -- This is valid only for 'ParamQuery' parameters and allows sending
472426 -- a parameter with an empty value. Default value is @false@.
473− , _paramAllowEmptyValue :: Maybe Bool
474−
475− -- | Determines whether the parameter value SHOULD allow reserved characters,
476− -- as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.2)
477− -- @:/?#[]@!$&'()*+,;=@ to be included without percent-encoding.
478− -- This property only applies to parameters with an '_paramIn' value of 'ParamQuery'.
479− -- The default value is 'False'.
480− , _paramAllowReserved :: Maybe Bool
427+ , _paramOtherSchemaAllowEmptyValue :: Maybe Bool
481428
482429 -- | Parameter schema.
483430 , _paramSchema :: Maybe (Referenced Schema)
484−
485− -- | Describes how the parameter value will be serialized depending
486− -- on the type of the parameter value. Default values (based on value of '_paramIn'):
487− -- for 'ParamQuery' - 'StyleForm'; for 'ParamPath' - 'StyleSimple'; for 'ParamHeader' - 'StyleSimple';
488− -- for 'ParamCookie' - 'StyleForm'.
489− , _paramStyle :: Maybe Style
490−
491− -- | When this is true, parameter values of type @array@ or @object@
492− -- generate separate parameters for each value of the array or key-value pair of the map.
493− -- For other types of parameters this property has no effect.
494− -- When style is @form@, the default value is true. For all other styles, the default value is false.
495− , _paramExplode :: Maybe Bool
496−
497− -- | Example of the parameter's potential value.
498− -- The example SHOULD match the specified schema and encoding properties if present.
499− -- The '_paramExample' field is mutually exclusive of the '_paramExamples' field.
500− -- Furthermore, if referencing a schema that contains an example, the example value
501− -- SHALL override the example provided by the schema. To represent examples of media types
502− -- that cannot naturally be represented in JSON or YAML, a string value can contain
503− -- the example with escaping where necessary.
504− , _paramExample :: Maybe Value
505−
506− -- | Examples of the parameter's potential value.
507− -- Each example SHOULD contain a value in the correct format as specified
508− -- in the parameter encoding. The '_paramExamples' field is mutually exclusive of the '_paramExample' field.
509− -- Furthermore, if referencing a schema that contains an example,
510− -- the examples value SHALL override the example provided by the schema.
511− , _paramExamples :: InsOrdHashMap Text (Referenced Example)
512−
513− -- TODO
514− -- _paramContent :: InsOrdHashMap MediaType MediaTypeObject
515− -- should be singleton. mutually exclusive with _paramSchema.
516431 } deriving (Eq, Show, Generic, Data, Typeable)
517432
518433data Example = Example
@@ -537,64 +452,138 @@ data Example = Example
537452 , _exampleExternalValue :: Maybe URL
538453 } deriving (Eq, Show, Generic, Typeable, Data)
539454
540−data ExpressionOrValue
541− = Expression Text
542− | Value Value
543− deriving (Eq, Show, Generic, Typeable, Data)
544−
545−-- | The Link object represents a possible design-time link for a response.
546−-- The presence of a link does not guarantee the caller's ability to successfully invoke it,
547−-- rather it provides a known relationship and traversal mechanism between responses and other operations.
548−data Link = Link
549− { -- | A relative or absolute URI reference to an OAS operation.
550− -- This field is mutually exclusive of the '_linkOperationId' field,
551− -- and MUST point to an 'Operation' Object. Relative '_linkOperationRef'
552− -- values MAY be used to locate an existing 'Operation' Object in the OpenAPI definition.
553− _linkOperationRef :: Maybe Text
554−
555− -- | The name of an /existing/, resolvable OAS operation, as defined with a unique
556− -- '_operationOperationId'. This field is mutually exclusive of the '_linkOperationRef' field.
557− , _linkOperationId :: Maybe Text
558−
559− -- | A map representing parameters to pass to an operation as specified with '_linkOperationId'
560− -- or identified via '_linkOperationRef'. The key is the parameter name to be used, whereas
561− -- the value can be a constant or an expression to be evaluated and passed to the linked operation.
562− -- The parameter name can be qualified using the parameter location @[{in}.]{name}@
563− -- for operations that use the same parameter name in different locations (e.g. path.id).
564− , _linkParameters :: InsOrdHashMap Text ExpressionOrValue
565−
566− -- | A literal value or @{expression}@ to use as a request body when calling the target operation.
567− , _linkRequestBody :: Maybe ExpressionOrValue
568−
569− -- | A description of the link.
570− , _linkDescription :: Maybe Text
571−
572− -- | A server object to be used by the target operation.
573− , _linkServer :: Maybe Server
574− } deriving (Eq, Show, Generic, Typeable, Data)
575−
576−-- | Items for @'OpenApiArray'@ schemas.
455+-- | Items for @'SwaggerArray'@ schemas.
577456--
578−-- __Warning__: OpenAPI 3.0 does not support tuple arrays. However, OpenAPI 3.1 will, as
579−-- it will incorporate Json Schema mostly verbatim.
457+-- @'SwaggerItemsPrimitive'@ should be used only for query params, headers and path pieces.
458+-- The @'CollectionFormat' t@ parameter specifies how elements of an array should be displayed.
459+-- Note that @fmt@ in @'SwaggerItemsPrimitive' fmt schema@ specifies format for elements of type @schema@.
460+-- This is different from the original Swagger's <http://swagger.io/specification/#itemsObject Items Object>.
580461--
581−-- @'OpenApiItemsObject'@ should be used to specify homogenous array @'Schema'@s.
462+-- @'SwaggerItemsObject'@ should be used to specify homogenous array @'Schema'@s.
582463--
583−-- @'OpenApiItemsArray'@ should be used to specify tuple @'Schema'@s.
584−data OpenApiItems where
585− OpenApiItemsObject :: Referenced Schema -> OpenApiItems
586− OpenApiItemsArray :: [Referenced Schema] -> OpenApiItems
587− deriving (Eq, Show, Typeable, Data)
588−
589−data OpenApiType where
590− OpenApiString :: OpenApiType
591− OpenApiNumber :: OpenApiType
592− OpenApiInteger :: OpenApiType
593− OpenApiBoolean :: OpenApiType
594− OpenApiArray :: OpenApiType
595− OpenApiNull :: OpenApiType
596− OpenApiObject :: OpenApiType
597− deriving (Eq, Show, Typeable, Generic, Data)
464+-- @'SwaggerItemsArray'@ should be used to specify tuple @'Schema'@s.
465+data SwaggerItems t where
466+ SwaggerItemsPrimitive :: Maybe (CollectionFormat k) -> ParamSchema k-> SwaggerItems k
467+ SwaggerItemsObject :: Referenced Schema -> SwaggerItems 'SwaggerKindSchema
468+ SwaggerItemsArray :: [Referenced Schema] -> SwaggerItems 'SwaggerKindSchema
469+ deriving (Typeable)
470+
471+deriving instance Eq (SwaggerItems t)
472+deriving instance Show (SwaggerItems t)
473+--deriving instance Typeable (SwaggerItems t)
474+
475+swaggerItemsPrimitiveConstr :: Constr
476+swaggerItemsPrimitiveConstr = mkConstr swaggerItemsDataType "SwaggerItemsPrimitive" [] Prefix
477+
478+swaggerItemsObjectConstr :: Constr
479+swaggerItemsObjectConstr = mkConstr swaggerItemsDataType "SwaggerItemsObject" [] Prefix
480+
481+swaggerItemsArrayConstr :: Constr
482+swaggerItemsArrayConstr = mkConstr swaggerItemsDataType "SwaggerItemsArray" [] Prefix
483+
484+swaggerItemsDataType :: DataType
485+swaggerItemsDataType = mkDataType "Data.Swagger.SwaggerItems" [swaggerItemsPrimitiveConstr]
486+
487+-- Note: unfortunately we have to write these Data instances by hand,
488+-- to get better contexts / avoid duplicate name when using standalone deriving
489+
490+instance Data t => Data (SwaggerItems ('SwaggerKindNormal t)) where
491+ -- TODO: define gfoldl
492+ gunfold k z c = case constrIndex c of
493+ 1 -> k (k (z SwaggerItemsPrimitive))
494+ _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems t)."
495+ toConstr _ = swaggerItemsPrimitiveConstr
496+ dataTypeOf _ = swaggerItemsDataType
497+
498+-- SwaggerItems SwaggerKindParamOtherSchema can be constructed using SwaggerItemsPrimitive only
499+instance Data (SwaggerItems 'SwaggerKindParamOtherSchema) where
500+ -- TODO: define gfoldl
501+ gunfold k z c = case constrIndex c of
502+ 1 -> k (k (z SwaggerItemsPrimitive))
503+ _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems SwaggerKindParamOtherSchema)."
504+ toConstr _ = swaggerItemsPrimitiveConstr
505+ dataTypeOf _ = swaggerItemsDataType
506+
507+instance Data (SwaggerItems 'SwaggerKindSchema) where
508+ gfoldl _ _ (SwaggerItemsPrimitive _ _) = error " Data.Data.gfoldl: Constructor SwaggerItemsPrimitive used to construct SwaggerItems SwaggerKindSchema"
509+ gfoldl k z (SwaggerItemsObject ref) = z SwaggerItemsObject `k` ref
510+ gfoldl k z (SwaggerItemsArray ref) = z SwaggerItemsArray `k` ref
511+
512+ gunfold k z c = case constrIndex c of
513+ 2 -> k (z SwaggerItemsObject)
514+ 3 -> k (z SwaggerItemsArray)
515+ _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems SwaggerKindSchema)."
516+
517+ toConstr (SwaggerItemsPrimitive _ _) = error "Not supported"
518+ toConstr (SwaggerItemsObject _) = swaggerItemsObjectConstr
519+ toConstr (SwaggerItemsArray _) = swaggerItemsArrayConstr
520+
521+ dataTypeOf _ = swaggerItemsDataType
522+
523+-- | Type used as a kind to avoid overlapping instances.
524+data SwaggerKind t
525+ = SwaggerKindNormal t
526+ | SwaggerKindParamOtherSchema
527+ | SwaggerKindSchema
528+ deriving (Typeable)
529+
530+deriving instance Typeable 'SwaggerKindNormal
531+deriving instance Typeable 'SwaggerKindParamOtherSchema
532+deriving instance Typeable 'SwaggerKindSchema
533+
534+-- TODO remove
535+type family SwaggerKindType (k :: SwaggerKind *) :: *
536+type instance SwaggerKindType ('SwaggerKindNormal t) = t
537+type instance SwaggerKindType 'SwaggerKindSchema = Schema
538+--type instance SwaggerKindType 'SwaggerKindParamOtherSchema = ParamOtherSchema
539+
540+data SwaggerType t where
541+ SwaggerString :: SwaggerType t
542+ SwaggerNumber :: SwaggerType t
543+ SwaggerInteger :: SwaggerType t
544+ SwaggerBoolean :: SwaggerType t
545+ SwaggerArray :: SwaggerType t
546+ SwaggerFile :: SwaggerType 'SwaggerKindParamOtherSchema
547+ SwaggerNull :: SwaggerType 'SwaggerKindSchema
548+ SwaggerObject :: SwaggerType 'SwaggerKindSchema
549+ deriving (Typeable)
550+
551+deriving instance Eq (SwaggerType t)
552+deriving instance Show (SwaggerType t)
553+
554+swaggerTypeConstr :: Data (SwaggerType t) => SwaggerType t -> Constr
555+swaggerTypeConstr t = mkConstr (dataTypeOf t) (show t) [] Prefix
556+
557+swaggerTypeDataType :: {- Data (SwaggerType t) => -} SwaggerType t -> DataType
558+swaggerTypeDataType _ = mkDataType "Data.Swagger.SwaggerType" swaggerTypeConstrs
559+
560+swaggerCommonTypes :: [SwaggerType k]
561+swaggerCommonTypes = [SwaggerString, SwaggerNumber, SwaggerInteger, SwaggerBoolean, SwaggerArray]
562+
563+swaggerParamTypes :: [SwaggerType 'SwaggerKindParamOtherSchema]
564+swaggerParamTypes = swaggerCommonTypes ++ [SwaggerFile]
565+
566+swaggerSchemaTypes :: [SwaggerType 'SwaggerKindSchema]
567+swaggerSchemaTypes = swaggerCommonTypes ++ [error "SwaggerFile is invalid SwaggerType Schema", SwaggerNull, SwaggerObject]
568+
569+swaggerTypeConstrs :: [Constr]
570+swaggerTypeConstrs = map swaggerTypeConstr (swaggerCommonTypes :: [SwaggerType 'SwaggerKindSchema])
571+ ++ [swaggerTypeConstr SwaggerFile, swaggerTypeConstr SwaggerNull, swaggerTypeConstr SwaggerObject]
572+
573+instance Typeable t => Data (SwaggerType ('SwaggerKindNormal t)) where
574+ gunfold = gunfoldEnum "SwaggerType" swaggerCommonTypes
575+ toConstr = swaggerTypeConstr
576+ dataTypeOf = swaggerTypeDataType
577+
578+instance Data (SwaggerType 'SwaggerKindParamOtherSchema) where
579+ gunfold = gunfoldEnum "SwaggerType ParamOtherSchema" swaggerParamTypes
580+ toConstr = swaggerTypeConstr
581+ dataTypeOf = swaggerTypeDataType
582+
583+instance Data (SwaggerType 'SwaggerKindSchema) where
584+ gunfold = gunfoldEnum "SwaggerType Schema" swaggerSchemaTypes
585+ toConstr = swaggerTypeConstr
586+ dataTypeOf = swaggerTypeDataType
598587
599588data ParamLocation
600589 = -- | Parameters that are appended to the URL.
@@ -612,6 +601,42 @@ data ParamLocation
612601
613602type Format = Text
614603
604+-- | Determines the format of the array.
605+data CollectionFormat t where
606+ -- Comma separated values: @foo,bar@.
607+ CollectionCSV :: CollectionFormat t
608+ -- Space separated values: @foo bar@.
609+ CollectionSSV :: CollectionFormat t
610+ -- Tab separated values: @foo\\tbar@.
611+ CollectionTSV :: CollectionFormat t
612+ -- Pipe separated values: @foo|bar@.
613+ CollectionPipes :: CollectionFormat t
614+ -- Corresponds to multiple parameter instances
615+ -- instead of multiple values for a single instance @foo=bar&foo=baz@.
616+ -- This is valid only for parameters in @'ParamQuery'@ or @'ParamFormData'@.
617+ CollectionMulti :: CollectionFormat 'SwaggerKindParamOtherSchema
618+ deriving (Typeable)
619+
620+deriving instance Eq (CollectionFormat t)
621+deriving instance Show (CollectionFormat t)
622+
623+collectionFormatConstr :: CollectionFormat t -> Constr
624+collectionFormatConstr cf = mkConstr collectionFormatDataType (show cf) [] Prefix
625+
626+collectionFormatDataType :: DataType
627+collectionFormatDataType = mkDataType "Data.Swagger.CollectionFormat" $
628+ map collectionFormatConstr collectionCommonFormats
629+
630+collectionCommonFormats :: [CollectionFormat t]
631+collectionCommonFormats = [ CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes ]
632+
633+instance Data t => Data (CollectionFormat ('SwaggerKindNormal t)) where
634+ gunfold = gunfoldEnum "CollectionFormat" collectionCommonFormats
635+ toConstr = collectionFormatConstr
636+ dataTypeOf _ = collectionFormatDataType
637+
638+deriving instance Data (CollectionFormat 'SwaggerKindParamOtherSchema)
639+
615640type ParamName = Text
616641
617642data Schema = Schema
@@ -638,33 +663,9 @@ data Schema = Schema
638663 , _schemaMaxProperties :: Maybe Integer
639664 , _schemaMinProperties :: Maybe Integer
640665
641− , -- | Declares the value of the parameter that the server will use if none is provided,
642− -- for example a @"count"@ to control the number of results per page might default to @100@
643− -- if not supplied by the client in the request.
644− -- (Note: "default" has no meaning for required parameters.)
645− -- Unlike JSON Schema this value MUST conform to the defined type for this parameter.
646− _schemaDefault :: Maybe Value
647−
648− , _schemaType :: Maybe OpenApiType
649− , _schemaFormat :: Maybe Format
650− , _schemaItems :: Maybe OpenApiItems
651− , _schemaMaximum :: Maybe Scientific
652− , _schemaExclusiveMaximum :: Maybe Bool
653− , _schemaMinimum :: Maybe Scientific
654− , _schemaExclusiveMinimum :: Maybe Bool
655− , _schemaMaxLength :: Maybe Integer
656− , _schemaMinLength :: Maybe Integer
657− , _schemaPattern :: Maybe Pattern
658− , _schemaMaxItems :: Maybe Integer
659− , _schemaMinItems :: Maybe Integer
660− , _schemaUniqueItems :: Maybe Bool
661− , _schemaEnum :: Maybe [Value]
662− , _schemaMultipleOf :: Maybe Scientific
666+ , _schemaParamSchema :: ParamSchema 'SwaggerKindSchema
663667 } deriving (Eq, Show, Generic, Data, Typeable)
664668
665−-- | Regex pattern for @string@ type.
666−type Pattern = Text
667−
668669data Discriminator = Discriminator
669670 { -- | The name of the property in the payload that will hold the discriminator value.
670671 _discriminatorPropertyName :: Text
@@ -680,9 +681,39 @@ data NamedSchema = NamedSchema
680681 , _namedSchemaSchema :: Schema
681682 } deriving (Eq, Show, Generic, Data, Typeable)
682683
684+-- | Regex pattern for @string@ type.
685+type Pattern = Text
686+
687+data ParamSchema (t :: SwaggerKind *) = ParamSchema
688+ { -- | Declares the value of the parameter that the server will use if none is provided,
689+ -- for example a @"count"@ to control the number of results per page might default to @100@
690+ -- if not supplied by the client in the request.
691+ -- (Note: "default" has no meaning for required parameters.)
692+ -- Unlike JSON Schema this value MUST conform to the defined type for this parameter.
693+ _paramSchemaDefault :: Maybe Value
694+
695+ , _paramSchemaType :: Maybe (SwaggerType t)
696+ , _paramSchemaFormat :: Maybe Format
697+ , _paramSchemaItems :: Maybe (SwaggerItems t)
698+ , _paramSchemaMaximum :: Maybe Scientific
699+ , _paramSchemaExclusiveMaximum :: Maybe Bool
700+ , _paramSchemaMinimum :: Maybe Scientific
701+ , _paramSchemaExclusiveMinimum :: Maybe Bool
702+ , _paramSchemaMaxLength :: Maybe Integer
703+ , _paramSchemaMinLength :: Maybe Integer
704+ , _paramSchemaPattern :: Maybe Pattern
705+ , _paramSchemaMaxItems :: Maybe Integer
706+ , _paramSchemaMinItems :: Maybe Integer
707+ , _paramSchemaUniqueItems :: Maybe Bool
708+ , _paramSchemaEnum :: Maybe [Value]
709+ , _paramSchemaMultipleOf :: Maybe Scientific
710+ } deriving (Eq, Show, Generic, Typeable)
711+
712+deriving instance (Typeable k, Data (Maybe (SwaggerType k)), Data (SwaggerItems k)) => Data (ParamSchema k)
713+
683714data Xml = Xml
684715 { -- | Replaces the name of the element/attribute used for the described schema property.
685− -- When defined within the @'OpenApiItems'@ (items), it will affect the name of the individual XML elements within the list.
716+ -- When defined within the @'SwaggerItems'@ (items), it will affect the name of the individual XML elements within the list.
686717 -- When defined alongside type being array (outside the items),
687718 -- it will affect the wrapping element and only if wrapped is true.
688719 -- If wrapped is false, it will be ignored.
@@ -734,46 +765,25 @@ data Response = Response
734765 -- | A map containing descriptions of potential response payloads.
735766 -- The key is a media type or media type range and the value describes it.
736767 -- For responses that match multiple keys, only the most specific key is applicable.
737− -- e.g. @text/plain@ overrides @text/\*@.
738− , _responseContent :: InsOrdHashMap MediaType MediaTypeObject
768+ -- e.g. @text/plain@ overrides @text/*@.
769+ , _responseContent :: InsOrdHashMap Text MediaTypeObject
739770
740771 -- | Maps a header name to its definition.
741772 , _responseHeaders :: InsOrdHashMap HeaderName (Referenced Header)
742773
743− -- | A map of operations links that can be followed from the response.
744− -- The key of the map is a short name for the link, following the naming
745− -- constraints of the names for 'Component' Objects.
746− , _responseLinks :: InsOrdHashMap Text (Referenced Link)
774+ -- TODO links
747775 } deriving (Eq, Show, Generic, Data, Typeable)
748776
749777instance IsString Response where
750− fromString s = Response (fromString s) mempty mempty mempty
751−
752−-- | A map of possible out-of band callbacks related to the parent operation.
753−-- Each value in the map is a 'PathItem' Object that describes a set of requests that
754−-- may be initiated by the API provider and the expected responses.
755−-- The key value used to identify the path item object is an expression, evaluated at runtime,
756−-- that identifies a URL to use for the callback operation.
757−newtype Callback = Callback (InsOrdHashMap Text PathItem)
758− deriving (Eq, Show, Generic, Data, Typeable)
778+ fromString s = Response (fromString s) mempty mempty
759779
760780type HeaderName = Text
761781
762−-- | Header fields have the same meaning as for 'Param'.
763−--
764−-- Style is always treated as 'StyleSimple', as it is the only value allowed for headers.
765782data Header = Header
766783 { -- | A short description of the header.
767− _headerDescription :: Maybe HeaderName
768−
769− , _headerRequired :: Maybe Bool
770− , _headerDeprecated :: Maybe Bool
771− , _headerAllowEmptyValue :: Maybe Bool
772− , _headerExplode :: Maybe Bool
773− , _headerExample :: Maybe Value
774− , _headerExamples :: InsOrdHashMap Text (Referenced Example)
784+ _headerDescription :: Maybe Text
775785
776− , _headerSchema :: Maybe (Referenced Schema)
786+ , _headerSchema :: ParamSchema ('SwaggerKindNormal Header)
777787 } deriving (Eq, Show, Generic, Data, Typeable)
778788
779789-- | The location of the API key.
@@ -797,17 +807,17 @@ type AuthorizationURL = Text
797807-- | The token URL to be used for OAuth2 flow. This SHOULD be in the form of a URL.
798808type TokenURL = Text
799809
800−newtype OAuth2ImplicitFlow
801− = OAuth2ImplicitFlow {_oAuth2ImplicitFlowAuthorizationUrl :: AuthorizationURL}
802− deriving (Eq, Show, Generic, Data, Typeable)
810+data OAuth2ImplicitFlow = OAuth2ImplicitFlow
811+ { _oAuth2ImplicitFlowAuthorizationUrl :: AuthorizationURL
812+ } deriving (Eq, Show, Generic, Data, Typeable)
803813
804−newtype OAuth2PasswordFlow
805− = OAuth2PasswordFlow {_oAuth2PasswordFlowTokenUrl :: TokenURL}
806− deriving (Eq, Show, Generic, Data, Typeable)
814+data OAuth2PasswordFlow = OAuth2PasswordFlow
815+ { _oAuth2PasswordFlowTokenUrl :: TokenURL
816+ } deriving (Eq, Show, Generic, Data, Typeable)
807817
808−newtype OAuth2ClientCredentialsFlow
809− = OAuth2ClientCredentialsFlow {_oAuth2ClientCredentialsFlowTokenUrl :: TokenURL}
810− deriving (Eq, Show, Generic, Data, Typeable)
818+data OAuth2ClientCredentialsFlow = OAuth2ClientCredentialsFlow
819+ { _oAuth2ClientCredentialsFlowTokenUrl :: TokenURL
820+ } deriving (Eq, Show, Generic, Data, Typeable)
811821
812822data OAuth2AuthorizationCodeFlow = OAuth2AuthorizationCodeFlow
813823 { _oAuth2AuthorizationCodeFlowAuthorizationUrl :: AuthorizationURL
@@ -840,50 +850,8 @@ data OAuth2Flows = OAuth2Flows
840850 , _oAuth2FlowsAuthorizationCode :: Maybe (OAuth2Flow OAuth2AuthorizationCodeFlow)
841851 } deriving (Eq, Show, Generic, Data, Typeable)
842852
843−type BearerFormat = Text
844−
845−data HttpSchemeType
846− = HttpSchemeBearer (Maybe BearerFormat)
847− | HttpSchemeBasic
848− | HttpSchemeCustom Text
849− deriving (Eq, Show, Generic, Data, Typeable)
850−
851−-- |
852−--
853−-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer Nothing))
854−-- {
855−-- "scheme": "bearer",
856−-- "type": "http"
857−-- }
858−--
859−-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer (Just "jwt")))
860−-- {
861−-- "bearerFormat": "jwt",
862−-- "scheme": "bearer",
863−-- "type": "http"
864−-- }
865−--
866−-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp HttpSchemeBasic)
867−-- {
868−-- "scheme": "basic",
869−-- "type": "http"
870−-- }
871−--
872−-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeCustom "CANARY"))
873−-- {
874−-- "scheme": "CANARY",
875−-- "type": "http"
876−-- }
877−--
878−-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeApiKey (ApiKeyParams "id" ApiKeyCookie))
879−-- {
880−-- "in": "cookie",
881−-- "name": "id",
882−-- "type": "apiKey"
883−-- }
884−--
885853data SecuritySchemeType
886− = SecuritySchemeHttp HttpSchemeType
854+ = SecuritySchemeHttp
887855 | SecuritySchemeApiKey ApiKeyParams
888856 | SecuritySchemeOAuth2 OAuth2Flows
889857 | SecuritySchemeOpenIdConnect URL
@@ -918,7 +886,7 @@ data Tag = Tag
918886 _tagName :: TagName
919887
920888 -- | A short description for the tag.
921− -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
889+ -- GFM syntax can be used for rich text representation.
922890 , _tagDescription :: Maybe Text
923891
924892 -- | Additional external documentation for this tag.
@@ -933,7 +901,7 @@ instance IsString Tag where
933901-- | Allows referencing an external resource for extended documentation.
934902data ExternalDocs = ExternalDocs
935903 { -- | A short description of the target documentation.
936− -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
904+ -- GFM syntax can be used for rich text representation.
937905 _externalDocsDescription :: Maybe Text
938906
939907 -- | The URL for the target documentation.
@@ -980,18 +948,18 @@ deriveGeneric ''MediaTypeObject
980948deriveGeneric ''Responses
981949deriveGeneric ''SecurityScheme
982950deriveGeneric ''Schema
983−deriveGeneric ''OpenApi
951+deriveGeneric ''ParamSchema
952+deriveGeneric ''Swagger
984953deriveGeneric ''Example
985954deriveGeneric ''Encoding
986−deriveGeneric ''Link
987955
988956-- =======================================================================
989957-- Monoid instances
990958-- =======================================================================
991959
992−instance Semigroup OpenApi where
960+instance Semigroup Swagger where
993961 (<>) = genericMappend
994−instance Monoid OpenApi where
962+instance Monoid Swagger where
995963 mempty = genericMempty
996964 mappend = (<>)
997965
@@ -1025,6 +993,12 @@ instance Monoid Schema where
1025993 mempty = genericMempty
1026994 mappend = (<>)
1027995
996+instance Semigroup (ParamSchema t) where
997+ (<>) = genericMappend
998+instance Monoid (ParamSchema t) where
999+ mempty = genericMempty
1000+ mappend = (<>)
1001+
10281002instance Semigroup Param where
10291003 (<>) = genericMappend
10301004instance Monoid Param where
@@ -1119,19 +1093,19 @@ instance SwaggerMonoid Info
11191093instance SwaggerMonoid Components
11201094instance SwaggerMonoid PathItem
11211095instance SwaggerMonoid Schema
1096+instance SwaggerMonoid (ParamSchema t)
11221097instance SwaggerMonoid Param
11231098instance SwaggerMonoid Responses
11241099instance SwaggerMonoid Response
11251100instance SwaggerMonoid ExternalDocs
11261101instance SwaggerMonoid Operation
11271102instance (Eq a, Hashable a) => SwaggerMonoid (InsOrdHashSet a)
1128−instance SwaggerMonoid SecurityDefinitions
11291103
11301104instance SwaggerMonoid MimeList
11311105deriving instance SwaggerMonoid URL
11321106
1133−instance SwaggerMonoid OpenApiType where
1134− swaggerMempty = OpenApiString
1107+instance SwaggerMonoid (SwaggerType t) where
1108+ swaggerMempty = SwaggerString
11351109 swaggerMappend _ y = y
11361110
11371111instance SwaggerMonoid ParamLocation where
@@ -1151,12 +1125,6 @@ instance Monoid a => SwaggerMonoid (Referenced a) where
11511125-- Simple Generic-based ToJSON instances
11521126-- =======================================================================
11531127
1154−instance ToJSON Style where
1155− toJSON = genericToJSON (jsonPrefix "Style")
1156−
1157−instance ToJSON OpenApiType where
1158− toJSON = genericToJSON (jsonPrefix "Swagger")
1159−
11601128instance ToJSON ParamLocation where
11611129 toJSON = genericToJSON (jsonPrefix "Param")
11621130
@@ -1206,12 +1174,6 @@ instance ToJSON OAuth2AuthorizationCodeFlow where
12061174-- Simple Generic-based FromJSON instances
12071175-- =======================================================================
12081176
1209−instance FromJSON Style where
1210− parseJSON = genericParseJSON (jsonPrefix "Style")
1211−
1212−instance FromJSON OpenApiType where
1213− parseJSON = genericParseJSON (jsonPrefix "Swagger")
1214−
12151177instance FromJSON ParamLocation where
12161178 parseJSON = genericParseJSON (jsonPrefix "Param")
12171179
@@ -1258,14 +1220,7 @@ instance FromJSON OAuth2AuthorizationCodeFlow where
12581220-- Manual ToJSON instances
12591221-- =======================================================================
12601222
1261−instance ToJSON MediaType where
1262− toJSON = toJSON . show
1263− toEncoding = toEncoding . show
1264−
1265−instance ToJSONKey MediaType where
1266− toJSONKey = JSON.toJSONKeyText (Text.pack . show)
1267−
1268−instance (Eq p, ToJSON p, AesonDefaultValue p) => ToJSON (OAuth2Flow p) where
1223+instance (Eq p, ToJSON p, AesonDefaultValue p) =>ToJSON (OAuth2Flow p) where
12691224 toJSON = sopSwaggerGenericToJSON
12701225 toEncoding = sopSwaggerGenericToEncoding
12711226
@@ -1274,19 +1229,8 @@ instance ToJSON OAuth2Flows where
12741229 toEncoding = sopSwaggerGenericToEncoding
12751230
12761231instance ToJSON SecuritySchemeType where
1277− toJSON (SecuritySchemeHttp ty) = case ty of
1278− HttpSchemeBearer mFmt ->
1279− object $ [ "type" .= ("http" :: Text)
1280− , "scheme" .= ("bearer" :: Text)
1281− ] <> maybe [] (\t -> ["bearerFormat" .= t]) mFmt
1282− HttpSchemeBasic ->
1283− object [ "type" .= ("http" :: Text)
1284− , "scheme" .= ("basic" :: Text)
1285− ]
1286− HttpSchemeCustom t ->
1287− object [ "type" .= ("http" :: Text)
1288− , "scheme" .= t
1289− ]
1232+ toJSON SecuritySchemeHttp
1233+ = object [ "type" .= ("http" :: Text) ]
12901234 toJSON (SecuritySchemeApiKey params)
12911235 = toJSON params
12921236 <+> object [ "type" .= ("apiKey" :: Text) ]
@@ -1299,9 +1243,9 @@ instance ToJSON SecuritySchemeType where
12991243 , "openIdConnectUrl" .= url
13001244 ]
13011245
1302−instance ToJSON OpenApi where
1246+instance ToJSON Swagger where
13031247 toJSON a = sopSwaggerGenericToJSON a &
1304− if InsOrdHashMap.null (_openApiPaths a)
1248+ if InsOrdHashMap.null (_swaggerPaths a)
13051249 then (<+> object ["paths" .= object []])
13061250 else id
13071251 toEncoding = sopSwaggerGenericToEncoding
@@ -1315,8 +1259,8 @@ instance ToJSON SecurityScheme where
13151259 toEncoding = sopSwaggerGenericToEncoding
13161260
13171261instance ToJSON Schema where
1318− toJSON = sopSwaggerGenericToJSONWithOpts $
1319− mkSwaggerAesonOptions "schema" & saoSubObject ?~ "items"
1262+ toJSON = sopSwaggerGenericToJSON
1263+ toEncoding = sopSwaggerGenericToEncoding
13201264
13211265instance ToJSON Header where
13221266 toJSON = sopSwaggerGenericToJSON
@@ -1325,21 +1269,20 @@ instance ToJSON Header where
13251269-- | As for nullary schema for 0-arity type constructors, see
13261270-- <https://github.com/GetShopTV/swagger2/issues/167>.
13271271--
1328−-- >>> BSL.putStrLn $ encodePretty (OpenApiItemsArray [])
1329−-- {
1330−-- "example": [],
1331−-- "items": {},
1332−-- "maxItems": 0
1333−-- }
1272+-- >>> encode (SwaggerItemsArray [])
1273+-- "{\"example\":[],\"items\":{},\"maxItems\":0}"
13341274--
1335−instance ToJSON OpenApiItems where
1336− toJSON (OpenApiItemsObject x) = object [ "items" .= x ]
1337− toJSON (OpenApiItemsArray []) = object
1275+instance ToJSON (ParamSchema t) => ToJSON (SwaggerItems t) where
1276+ toJSON (SwaggerItemsPrimitive fmt schema) = object
1277+ [ "collectionFormat" .= fmt
1278+ , "items" .= schema ]
1279+ toJSON (SwaggerItemsObject x) = object [ "items" .= x ]
1280+ toJSON (SwaggerItemsArray []) = object
13381281 [ "items" .= object []
13391282 , "maxItems" .= (0 :: Int)
13401283 , "example" .= Array mempty
13411284 ]
1342− toJSON (OpenApiItemsArray x) = object [ "items" .= x ]
1285+ toJSON (SwaggerItemsArray x) = object [ "items" .= x ]
13431286
13441287instance ToJSON Components where
13451288 toJSON = sopSwaggerGenericToJSON
@@ -1384,10 +1327,6 @@ instance ToJSON Encoding where
13841327 toJSON = sopSwaggerGenericToJSON
13851328 toEncoding = sopSwaggerGenericToEncoding
13861329
1387−instance ToJSON Link where
1388− toJSON = sopSwaggerGenericToJSON
1389− toEncoding = sopSwaggerGenericToEncoding
1390−
13911330instance ToJSON SecurityDefinitions where
13921331 toJSON (SecurityDefinitions sd) = toJSON sd
13931332
@@ -1404,31 +1343,37 @@ instance ToJSON (Referenced Response) where toJSON = referencedToJSON "#/compone
14041343instance ToJSON (Referenced RequestBody) where toJSON = referencedToJSON "#/components/requestBodies/"
14051344instance ToJSON (Referenced Example) where toJSON = referencedToJSON "#/components/examples/"
14061345instance ToJSON (Referenced Header) where toJSON = referencedToJSON "#/components/headers/"
1407−instance ToJSON (Referenced Link) where toJSON = referencedToJSON "#/components/links/"
1408−instance ToJSON (Referenced Callback) where toJSON = referencedToJSON "#/components/callbacks/"
1346+
1347+instance ToJSON (SwaggerType t) where
1348+ toJSON SwaggerArray = "array"
1349+ toJSON SwaggerString = "string"
1350+ toJSON SwaggerInteger = "integer"
1351+ toJSON SwaggerNumber = "number"
1352+ toJSON SwaggerBoolean = "boolean"
1353+ toJSON SwaggerFile = "file"
1354+ toJSON SwaggerNull = "null"
1355+ toJSON SwaggerObject = "object"
1356+
1357+instance ToJSON (CollectionFormat t) where
1358+ toJSON CollectionCSV = "csv"
1359+ toJSON CollectionSSV = "ssv"
1360+ toJSON CollectionTSV = "tsv"
1361+ toJSON CollectionPipes = "pipes"
1362+ toJSON CollectionMulti = "multi"
1363+
1364+instance ToJSON (ParamSchema k) where
1365+ -- TODO: this is a bit fishy, why we need sub object only in `ToJSON`?
1366+ toJSON = sopSwaggerGenericToJSONWithOpts $
1367+ mkSwaggerAesonOptions "paramSchema" & saoSubObject ?~ "items"
14091368
14101369instance ToJSON AdditionalProperties where
14111370 toJSON (AdditionalPropertiesAllowed b) = toJSON b
14121371 toJSON (AdditionalPropertiesSchema s) = toJSON s
14131372
1414−instance ToJSON ExpressionOrValue where
1415− toJSON (Expression expr) = toJSON expr
1416− toJSON (Value val) = toJSON val
1417−
1418−instance ToJSON Callback where
1419− toJSON (Callback ps) = toJSON ps
1420−
14211373-- =======================================================================
14221374-- Manual FromJSON instances
14231375-- =======================================================================
14241376
1425−instance FromJSON MediaType where
1426− parseJSON = withText "MediaType" $ \str ->
1427− maybe (fail $ "Invalid media type literal " <> Text.unpack str) pure $ parseAccept $ encodeUtf8 str
1428−
1429−instance FromJSONKey MediaType where
1430− fromJSONKey = FromJSONKeyTextParser (parseJSON . String)
1431−
14321377instance (Eq p, FromJSON p, AesonDefaultValue p) => FromJSON (OAuth2Flow p) where
14331378 parseJSON = sopSwaggerGenericParseJSON
14341379
@@ -1439,19 +1384,14 @@ instance FromJSON SecuritySchemeType where
14391384 parseJSON js@(Object o) = do
14401385 (t :: Text) <- o .: "type"
14411386 case t of
1442− "http" -> do
1443− scheme <- o .: "scheme"
1444− SecuritySchemeHttp <$> case scheme of
1445− "bearer" -> HttpSchemeBearer <$> (o .:! "bearerFormat")
1446− "basic" -> pure HttpSchemeBasic
1447− t -> pure $ HttpSchemeCustom t
1387+ "http" -> pure SecuritySchemeHttp
14481388 "apiKey" -> SecuritySchemeApiKey <$> parseJSON js
14491389 "oauth2" -> SecuritySchemeOAuth2 <$> (o .: "flows")
14501390 "openIdConnect" -> SecuritySchemeOpenIdConnect <$> (o .: "openIdConnectUrl")
14511391 _ -> empty
14521392 parseJSON _ = empty
14531393
1454−instance FromJSON OpenApi where
1394+instance FromJSON Swagger where
14551395 parseJSON = sopSwaggerGenericParseJSON
14561396
14571397instance FromJSON Server where
@@ -1463,28 +1403,48 @@ instance FromJSON SecurityScheme where
14631403instance FromJSON Schema where
14641404 parseJSON = fmap nullaryCleanup . sopSwaggerGenericParseJSON
14651405 where nullaryCleanup :: Schema -> Schema
1466− nullaryCleanup s =
1467− if _schemaItems s == Just (OpenApiItemsArray [])
1406+ nullaryCleanup s@Schema{_schemaParamSchema=ps} =
1407+ if _paramSchemaItems ps == Just (SwaggerItemsArray [])
14681408 then s { _schemaExample = Nothing
1469− , _schemaMaxItems = Nothing
1470− }
1409+ , _schemaParamSchema = ps { _paramSchemaMaxItems = Nothing } }
14711410 else s
14721411
14731412instance FromJSON Header where
14741413 parseJSON = sopSwaggerGenericParseJSON
14751414
1476−instance FromJSON OpenApiItems where
1415+instance (FromJSON (CollectionFormat ('SwaggerKindNormal t)), FromJSON (ParamSchema ('SwaggerKindNormal t))) => FromJSON (SwaggerItems ('SwaggerKindNormal t)) where
1416+ parseJSON = withObject "SwaggerItemsPrimitive" $ \o -> SwaggerItemsPrimitive
1417+ <$> o .:? "collectionFormat"
1418+ <*> (o .: "items" >>= parseJSON)
1419+
1420+instance FromJSON (SwaggerItems 'SwaggerKindParamOtherSchema) where
1421+ parseJSON = withObject "SwaggerItemsPrimitive" $ \o -> SwaggerItemsPrimitive
1422+ <$> o .:? "collectionFormat"
1423+ <*> ((o .: "items" >>= parseJSON) <|> fail ("foo" ++ show o))
1424+
1425+-- |
1426+--
1427+-- >>> decode "{}" :: Maybe (SwaggerItems 'SwaggerKindSchema)
1428+-- Just (SwaggerItemsArray [])
1429+--
1430+-- >>> eitherDecode "{\"$ref\":\"#/components/schemas/example\"}" :: Either String (SwaggerItems 'SwaggerKindSchema)
1431+-- Right (SwaggerItemsObject (Ref (Reference {getReference = "example"})))
1432+--
1433+-- >>> eitherDecode "[{\"$ref\":\"#/components/schemas/example\"}]" :: Either String (SwaggerItems 'SwaggerKindSchema)
1434+-- Right (SwaggerItemsArray [Ref (Reference {getReference = "example"})])
1435+--
1436+instance FromJSON (SwaggerItems 'SwaggerKindSchema) where
14771437 parseJSON js@(Object obj)
1478− | null obj = pure $ OpenApiItemsArray [] -- Nullary schema.
1479− | otherwise = OpenApiItemsObject <$> parseJSON js
1480− parseJSON js@(Array _) = OpenApiItemsArray <$> parseJSON js
1438+ | null obj = pure $ SwaggerItemsArray [] -- Nullary schema.
1439+ | otherwise = SwaggerItemsObject <$> parseJSON js
1440+ parseJSON js@(Array _) = SwaggerItemsArray <$> parseJSON js
14811441 parseJSON _ = empty
14821442
14831443instance FromJSON Components where
14841444 parseJSON = sopSwaggerGenericParseJSON
14851445
14861446instance FromJSON MimeList where
1487− parseJSON js = MimeList . map fromString <$> parseJSON js
1447+ parseJSON js = (MimeList . map fromString) <$> parseJSON js
14881448
14891449instance FromJSON Param where
14901450 parseJSON = sopSwaggerGenericParseJSON
@@ -1492,7 +1452,7 @@ instance FromJSON Param where
14921452instance FromJSON Responses where
14931453 parseJSON (Object o) = Responses
14941454 <$> o .:? "default"
1495− <*> parseJSON (Object (deleteKey "default" o))
1455+ <*> (parseJSON (Object (HashMap.delete "default" o)))
14961456 parseJSON _ = empty
14971457
14981458instance FromJSON Example where
@@ -1519,9 +1479,6 @@ instance FromJSON MediaTypeObject where
15191479instance FromJSON Encoding where
15201480 parseJSON = sopSwaggerGenericParseJSON
15211481
1522−instance FromJSON Link where
1523− parseJSON = sopSwaggerGenericParseJSON
1524−
15251482instance FromJSON Reference where
15261483 parseJSON (Object o) = Reference <$> o .: "$ref"
15271484 parseJSON _ = empty
@@ -1545,24 +1502,40 @@ instance FromJSON (Referenced Response) where parseJSON = referencedParseJSON "#
15451502instance FromJSON (Referenced RequestBody) where parseJSON = referencedParseJSON "#/components/requestBodies/"
15461503instance FromJSON (Referenced Example) where parseJSON = referencedParseJSON "#/components/examples/"
15471504instance FromJSON (Referenced Header) where parseJSON = referencedParseJSON "#/components/headers/"
1548−instance FromJSON (Referenced Link) where parseJSON = referencedParseJSON "#/components/links/"
1549−instance FromJSON (Referenced Callback) where parseJSON = referencedParseJSON "#/components/callbacks/"
15501505
15511506instance FromJSON Xml where
15521507 parseJSON = genericParseJSON (jsonPrefix "xml")
15531508
1509+instance FromJSON (SwaggerType 'SwaggerKindSchema) where
1510+ parseJSON = parseOneOf [SwaggerString, SwaggerInteger, SwaggerNumber, SwaggerBoolean, SwaggerArray, SwaggerNull, SwaggerObject]
1511+
1512+instance FromJSON (SwaggerType 'SwaggerKindParamOtherSchema) where
1513+ parseJSON = parseOneOf [SwaggerString, SwaggerInteger, SwaggerNumber, SwaggerBoolean, SwaggerArray, SwaggerFile]
1514+
1515+instance FromJSON (SwaggerType ('SwaggerKindNormal t)) where
1516+ parseJSON = parseOneOf [SwaggerString, SwaggerInteger, SwaggerNumber, SwaggerBoolean, SwaggerArray]
1517+
1518+instance FromJSON (CollectionFormat ('SwaggerKindNormal t)) where
1519+ parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes]
1520+
1521+-- NOTE: There aren't collections of 'Schema'
1522+--instance FromJSON (CollectionFormat (SwaggerKindSchema)) where
1523+-- parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes]
1524+
1525+instance FromJSON (CollectionFormat 'SwaggerKindParamOtherSchema) where
1526+ parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes, CollectionMulti]
1527+
1528+instance (FromJSON (SwaggerType ('SwaggerKindNormal t)), FromJSON (SwaggerItems ('SwaggerKindNormal t))) => FromJSON (ParamSchema ('SwaggerKindNormal t)) where
1529+ parseJSON = sopSwaggerGenericParseJSON
1530+instance FromJSON (ParamSchema 'SwaggerKindParamOtherSchema) where
1531+ parseJSON = sopSwaggerGenericParseJSON
1532+instance FromJSON (ParamSchema 'SwaggerKindSchema) where
1533+ parseJSON = sopSwaggerGenericParseJSON
1534+
15541535instance FromJSON AdditionalProperties where
15551536 parseJSON (Bool b) = pure $ AdditionalPropertiesAllowed b
15561537 parseJSON js = AdditionalPropertiesSchema <$> parseJSON js
15571538
1558−-- | All strings are parsed as expressions
1559−instance FromJSON ExpressionOrValue where
1560− parseJSON (String expr) = pure $ Expression expr
1561− parseJSON v = pure $ Value v
1562−
1563−instance FromJSON Callback where
1564− parseJSON = fmap Callback . parseJSON
1565−
15661539instance HasSwaggerAesonOptions Server where
15671540 swaggerAesonOptions _ = mkSwaggerAesonOptions "server"
15681541instance HasSwaggerAesonOptions Components where
@@ -1591,18 +1564,24 @@ instance HasSwaggerAesonOptions SecurityScheme where
15911564 swaggerAesonOptions _ = mkSwaggerAesonOptions "securityScheme" & saoSubObject ?~ "type"
15921565instance HasSwaggerAesonOptions Schema where
15931566 swaggerAesonOptions _ = mkSwaggerAesonOptions "schema" & saoSubObject ?~ "paramSchema"
1594−instance HasSwaggerAesonOptions OpenApi where
1567+instance HasSwaggerAesonOptions Swagger where
15951568 swaggerAesonOptions _ = mkSwaggerAesonOptions "swagger" & saoAdditionalPairs .~ [("openapi", "3.0.0")]
15961569instance HasSwaggerAesonOptions Example where
15971570 swaggerAesonOptions _ = mkSwaggerAesonOptions "example"
15981571instance HasSwaggerAesonOptions Encoding where
15991572 swaggerAesonOptions _ = mkSwaggerAesonOptions "encoding"
16001573
1601−instance HasSwaggerAesonOptions Link where
1602− swaggerAesonOptions _ = mkSwaggerAesonOptions "link"
1574+instance HasSwaggerAesonOptions (ParamSchema ('SwaggerKindNormal t)) where
1575+ swaggerAesonOptions _ = mkSwaggerAesonOptions "paramSchema" & saoSubObject ?~ "items"
1576+instance HasSwaggerAesonOptions (ParamSchema 'SwaggerKindParamOtherSchema) where
1577+ swaggerAesonOptions _ = mkSwaggerAesonOptions "paramSchema" & saoSubObject ?~ "items"
1578+-- NOTE: Schema doesn't have 'items' sub object!
1579+instance HasSwaggerAesonOptions (ParamSchema 'SwaggerKindSchema) where
1580+ swaggerAesonOptions _ = mkSwaggerAesonOptions "paramSchema"
16031581
16041582instance AesonDefaultValue Server
16051583instance AesonDefaultValue Components
1584+instance AesonDefaultValue (ParamSchema s)
16061585instance AesonDefaultValue OAuth2ImplicitFlow
16071586instance AesonDefaultValue OAuth2PasswordFlow
16081587instance AesonDefaultValue OAuth2ClientCredentialsFlow
@@ -1610,10 +1589,7 @@ instance AesonDefaultValue OAuth2AuthorizationCodeFlow
16101589instance AesonDefaultValue p => AesonDefaultValue (OAuth2Flow p)
16111590instance AesonDefaultValue Responses
16121591instance AesonDefaultValue SecuritySchemeType
1613−instance AesonDefaultValue OpenApiType
1592+instance AesonDefaultValue (SwaggerType a)
16141593instance AesonDefaultValue MimeList where defaultValue = Just mempty
16151594instance AesonDefaultValue Info
16161595instance AesonDefaultValue ParamLocation
1617−instance AesonDefaultValue Link
1618−instance AesonDefaultValue SecurityDefinitions where
1619− defaultValue = Just mempty