@@ -0,0 +1,1619 @@
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE DeriveDataTypeable #-}
4+{-# LANGUAGE DeriveGeneric #-}
5+{-# LANGUAGE DeriveTraversable #-}
6+{-# LANGUAGE FlexibleContexts #-}
7+{-# LANGUAGE FlexibleInstances #-}
9+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10+{-# LANGUAGE OverloadedStrings #-}
11+{-# LANGUAGE RecordWildCards #-}
12+{-# LANGUAGE ScopedTypeVariables #-}
13+{-# LANGUAGE StandaloneDeriving #-}
14+{-# LANGUAGE TemplateHaskell #-}
15+{-# LANGUAGE TypeFamilies #-}
16+{-# LANGUAGE UndecidableInstances #-}
17+module Data.OpenApi.Internal where
22+import 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
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)
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, (//),
46+import Network.Socket (HostName, PortNumber)
47+import Text.Read (readMaybe)
49+import Data.HashMap.Strict.InsOrd (InsOrdHashMap)
50+import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
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
58+import Generics.SOP.TH (deriveGeneric)
61+-- >>> :seti -XDataKinds
62+-- >>> import Data.Aeson
63+-- >>> import Data.ByteString.Lazy.Char8 as BSL
64+-- >>> import Data.OpenApi.Internal.Utils
66+-- | A list of definitions that can be used in references.
67+type Definitions = InsOrdHashMap Text
69+-- | This is the root document object for the API specification.
70+data OpenApi = OpenApi
71+ { -- | Provides metadata about the API.
72+ -- The metadata can be used by the clients if needed.
75+ -- | An array of Server Objects, which provide connectivity information
76+ -- to a target server. If the servers property is not provided, or is an empty array,
77+ -- the default value would be a 'Server' object with a url value of @/@.
78+ , _openApiServers :: [Server]
80+ -- | The available paths and operations for the API.
81+ , _openApiPaths :: InsOrdHashMap FilePath PathItem
83+ -- | An element to hold various schemas for the specification.
84+ , _openApiComponents :: Components
86+ -- | A declaration of which security mechanisms can be used across the API.
87+ -- The list of values includes alternative security requirement objects that can be used.
88+ -- Only one of the security requirement objects need to be satisfied to authorize a request.
89+ -- Individual operations can override this definition.
90+ -- To make security optional, an empty security requirement can be included in the array.
91+ , _openApiSecurity :: [SecurityRequirement]
93+ -- | A list of tags used by the specification with additional metadata.
94+ -- The order of the tags can be used to reflect on their order by the parsing tools.
95+ -- Not all tags that are used by the 'Operation' Object must be declared.
96+ -- The tags that are not declared MAY be organized randomly or based on the tools' logic.
97+ -- Each tag name in the list MUST be unique.
98+ , _openApiTags :: InsOrdHashSet Tag
100+ -- | Additional external documentation.
101+ , _openApiExternalDocs :: Maybe ExternalDocs
102+ } deriving (Eq, Show, Generic, Data, Typeable)
104+-- | The object provides metadata about the API.
105+-- The metadata MAY be used by the clients if needed,
106+-- and MAY be presented in editing or documentation generation tools for convenience.
108+ { -- | The title of the API.
111+ -- | A short description of the API.
112+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
113+ , _infoDescription :: Maybe Text
115+ -- | A URL to the Terms of Service for the API. MUST be in the format of a URL.
116+ , _infoTermsOfService :: Maybe Text
118+ -- | The contact information for the exposed API.
119+ , _infoContact :: Maybe Contact
121+ -- | The license information for the exposed API.
122+ , _infoLicense :: Maybe License
124+ -- | The version of the OpenAPI document (which is distinct from the
125+ -- OpenAPI Specification version or the API implementation version).
126+ , _infoVersion :: Text
127+ } deriving (Eq, Show, Generic, Data, Typeable)
129+-- | Contact information for the exposed API.
130+data Contact = Contact
131+ { -- | The identifying name of the contact person/organization.
132+ _contactName :: Maybe Text
134+ -- | The URL pointing to the contact information.
135+ , _contactUrl :: Maybe URL
137+ -- | The email address of the contact person/organization.
138+ , _contactEmail :: Maybe Text
139+ } deriving (Eq, Show, Generic, Data, Typeable)
141+-- | License information for the exposed API.
142+data License = License
143+ { -- | The license name used for the API.
144+ _licenseName :: Text
146+ -- | A URL to the license used for the API.
147+ , _licenseUrl :: Maybe URL
148+ } deriving (Eq, Show, Generic, Data, Typeable)
150+instance IsString License where
151+ fromString s = License (fromString s) Nothing
153+-- | An object representing a Server.
155+ { -- | A URL to the target host. This URL supports Server Variables and MAY be relative,
156+ -- to indicate that the host location is relative to the location where
157+ -- the OpenAPI document is being served. Variable substitutions will be made when
158+ -- a variable is named in @{brackets}@.
161+ -- | An optional string describing the host designated by the URL.
162+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
163+ , _serverDescription :: Maybe Text
165+ -- | A map between a variable name and its value.
166+ -- The value is used for substitution in the server's URL template.
167+ , _serverVariables :: InsOrdHashMap Text ServerVariable
168+ } deriving (Eq, Show, Generic, Data, Typeable)
170+data ServerVariable = ServerVariable
171+ { -- | An enumeration of string values to be used if the substitution options
172+ -- are from a limited set. The array SHOULD NOT be empty.
173+ _serverVariableEnum :: Maybe (InsOrdHashSet Text) -- TODO NonEmpty
175+ -- | The default value to use for substitution, which SHALL be sent if an alternate value
176+ -- is not supplied. Note this behavior is different than the 'Schema\ Object's treatment
177+ -- of default values, because in those cases parameter values are optional.
178+ -- If the '_serverVariableEnum' is defined, the value SHOULD exist in the enum's values.
179+ , _serverVariableDefault :: Text
181+ -- | An optional description for the server variable.
182+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
183+ , _serverVariableDescription :: Maybe Text
184+ } deriving (Eq, Show, Generic, Data, Typeable)
186+instance IsString Server where
187+ fromString s = Server (fromString s) Nothing mempty
189+-- | Holds a set of reusable objects for different aspects of the OAS.
190+-- All objects defined within the components object will have no effect on the API
191+-- unless they are explicitly referenced from properties outside the components object.
192+data Components = Components
193+ { _componentsSchemas :: Definitions Schema
194+ , _componentsResponses :: Definitions Response
195+ , _componentsParameters :: Definitions Param
196+ , _componentsExamples :: Definitions Example
197+ , _componentsRequestBodies :: Definitions RequestBody
198+ , _componentsHeaders :: Definitions Header
199+ , _componentsSecuritySchemes :: SecurityDefinitions
200+ , _componentsLinks :: Definitions Link
201+ , _componentsCallbacks :: Definitions Callback
202+ } deriving (Eq, Show, Generic, Data, Typeable)
204+-- | Describes the operations available on a single path.
205+-- A @'PathItem'@ may be empty, due to ACL constraints.
206+-- The path itself is still exposed to the documentation viewer
207+-- but they will not know which operations and parameters are available.
208+data PathItem = PathItem
209+ { -- | An optional, string summary, intended to apply to all operations in this path.
210+ _pathItemSummary :: Maybe Text
212+ -- | An optional, string description, intended to apply to all operations in this path.
213+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
214+ , _pathItemDescription :: Maybe Text
216+ -- | A definition of a GET operation on this path.
217+ , _pathItemGet :: Maybe Operation
219+ -- | A definition of a PUT operation on this path.
220+ , _pathItemPut :: Maybe Operation
222+ -- | A definition of a POST operation on this path.
223+ , _pathItemPost :: Maybe Operation
225+ -- | A definition of a DELETE operation on this path.
226+ , _pathItemDelete :: Maybe Operation
228+ -- | A definition of a OPTIONS operation on this path.
229+ , _pathItemOptions :: Maybe Operation
231+ -- | A definition of a HEAD operation on this path.
232+ , _pathItemHead :: Maybe Operation
234+ -- | A definition of a PATCH operation on this path.
235+ , _pathItemPatch :: Maybe Operation
237+ -- | A definition of a TRACE operation on this path.
238+ , _pathItemTrace :: Maybe Operation
240+ -- | An alternative server array to service all operations in this path.
241+ , _pathItemServers :: [Server]
243+ -- | A list of parameters that are applicable for all the operations described under this path.
244+ -- These parameters can be overridden at the operation level, but cannot be removed there.
245+ -- The list MUST NOT include duplicated parameters.
246+ -- A unique parameter is defined by a combination of a name and location.
247+ , _pathItemParameters :: [Referenced Param]
248+ } deriving (Eq, Show, Generic, Data, Typeable)
250+-- | Describes a single API operation on a path.
251+data Operation = Operation
252+ { -- | A list of tags for API documentation control.
253+ -- Tags can be used for logical grouping of operations by resources or any other qualifier.
254+ _operationTags :: InsOrdHashSet TagName
256+ -- | A short summary of what the operation does.
257+ -- For maximum readability in the swagger-ui, this field SHOULD be less than 120 characters.
258+ , _operationSummary :: Maybe Text
260+ -- | A verbose explanation of the operation behavior.
261+ -- [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
262+ , _operationDescription :: Maybe Text
264+ -- | Additional external documentation for this operation.
265+ , _operationExternalDocs :: Maybe ExternalDocs
267+ -- | Unique string used to identify the operation.
268+ -- The id MUST be unique among all operations described in the API.
269+ -- The operationId value is **case-sensitive**.
270+ -- Tools and libraries MAY use the operationId to uniquely identify an operation, therefore,
271+ -- it is RECOMMENDED to follow common programming naming conventions.
272+ , _operationOperationId :: Maybe Text
274+ -- | A list of parameters that are applicable for this operation.
275+ -- If a parameter is already defined at the @'PathItem'@,
276+ -- the new definition will override it, but can never remove it.
277+ -- The list MUST NOT include duplicated parameters.
278+ -- A unique parameter is defined by a combination of a name and location.
279+ , _operationParameters :: [Referenced Param]
281+ -- | The request body applicable for this operation.
282+ -- The requestBody is only supported in HTTP methods where the HTTP 1.1
283+ -- specification [RFC7231](https://tools.ietf.org/html/rfc7231#section-4.3.1)
284+ -- has explicitly defined semantics for request bodies.
285+ -- In other cases where the HTTP spec is vague, requestBody SHALL be ignored by consumers.
286+ , _operationRequestBody :: Maybe (Referenced RequestBody)
288+ -- | The list of possible responses as they are returned from executing this operation.
289+ , _operationResponses :: Responses
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)
297+ -- | Declares this operation to be deprecated.
298+ -- Usage of the declared operation should be refrained.
299+ -- Default value is @False@.
300+ , _operationDeprecated :: Maybe Bool
302+ -- | A declaration of which security schemes are applied for this operation.
303+ -- The list of values describes alternative security schemes that can be used
304+ -- (that is, there is a logical OR between the security requirements).
305+ -- This definition overrides any declared top-level security.
306+ -- To remove a top-level security declaration, @Just []@ can be used.
307+ , _operationSecurity :: [SecurityRequirement]
309+ -- | An alternative server array to service this operation.
310+ -- If an alternative server object is specified at the 'PathItem' Object or Root level,
311+ -- it will be overridden by this value.
312+ , _operationServers :: [Server]
313+ } deriving (Eq, Show, Generic, Data, Typeable)
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."
321+ toConstr _ = mediaTypeConstr
323+ dataTypeOf _ = mediaTypeData
325+mediaTypeConstr = mkConstr mediaTypeData "MediaType" [] Prefix
326+mediaTypeData = mkDataType "MediaType" [mediaTypeConstr]
328+instance Hashable MediaType where
329+ hashWithSalt salt mt = salt `hashWithSalt` show mt
331+-- | Describes a single request body.
332+data RequestBody = RequestBody
333+ { -- | A brief description of the request body. This could contain examples of use.
334+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
335+ _requestBodyDescription :: Maybe Text
337+ -- | The content of the request body.
338+ -- The key is a media type or media type range and the value describes it.
339+ -- 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
343+ -- | Determines if the request body is required in the request.
344+ -- Defaults to 'False'.
345+ , _requestBodyRequired :: Maybe Bool
346+ } deriving (Eq, Show, Generic, Data, Typeable)
348+-- | Each Media Type Object provides schema and examples for the media type identified by its key.
349+data MediaTypeObject = MediaTypeObject
350+ { _mediaTypeObjectSchema :: Maybe (Referenced Schema)
352+ -- | Example of the media type.
353+ -- The example object SHOULD be in the correct format as specified by the media type.
354+ , _mediaTypeObjectExample :: Maybe Value
356+ -- | Examples of the media type.
357+ -- Each example object SHOULD match the media type and specified schema if present.
358+ , _mediaTypeObjectExamples :: InsOrdHashMap Text (Referenced Example)
360+ -- | A map between a property name and its encoding information.
361+ -- The key, being the property name, MUST exist in the schema as a property.
362+ -- The encoding object SHALL only apply to 'RequestBody' objects when the media type
363+ -- is @multipart@ or @application/x-www-form-urlencoded@.
364+ , _mediaTypeObjectEncoding :: InsOrdHashMap Text Encoding
365+ } deriving (Eq, Show, Generic, Data, Typeable)
367+-- | In order to support common ways of serializing simple parameters, a set of style values are defined.
370+ -- ^ Path-style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
372+ -- ^ Label style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
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.
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.
387+ -- ^ Provides a simple way of rendering nested objects using form parameters.
388+ deriving (Eq, Show, Generic, Data, Typeable)
390+data Encoding = Encoding
391+ { -- | The Content-Type for encoding a specific property.
392+ -- Default value depends on the property type: for @string@
393+ -- with format being @binary@ – @application/octet-stream@;
394+ -- for other primitive types – @text/plain@; for object - @application/json@;
395+ -- for array – the default is defined based on the inner type.
396+ -- 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
400+ -- | A map allowing additional information to be provided as headers,
401+ -- for example @Content-Disposition@. @Content-Type@ is described separately
402+ -- and SHALL be ignored in this section.
403+ -- This property SHALL be ignored if the request body media type is not a @multipart@.
404+ , _encodingHeaders :: InsOrdHashMap Text (Referenced Header)
406+ -- | Describes how a specific property value will be serialized depending on its type.
407+ -- See 'Param' Object for details on the style property.
408+ -- The behavior follows the same values as query parameters, including default values.
409+ -- This property SHALL be ignored if the request body media type
410+ -- is not @application/x-www-form-urlencoded@.
411+ , _encodingStyle :: Maybe Style
413+ -- | When this is true, property values of type @array@ or @object@ generate
414+ -- separate parameters for each value of the array,
415+ -- or key-value-pair of the map.
416+ -- For other types of properties this property has no effect.
417+ -- When style is form, the default value is @true@. For all other styles,
418+ -- the default value is @false@. This property SHALL be ignored
419+ -- if the request body media type is not @application/x-www-form-urlencoded@.
420+ , _encodingExplode :: Maybe Bool
422+ -- | Determines whether the parameter value SHOULD allow reserved characters,
423+ -- as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.2)
424+ -- @:/?#[]@!$&'()*+,;=@ to be included without percent-encoding.
425+ -- The default value is @false@. This property SHALL be ignored if the request body media type
426+ -- is not @application/x-www-form-urlencoded@.
427+ , _encodingAllowReserved :: Maybe Bool
428+ } deriving (Eq, Show, Generic, Data, Typeable)
430+newtype MimeList = MimeList { getMimeList :: [MediaType] }
431+ deriving (Eq, Show, Semigroup, Monoid, Typeable)
433+mimeListConstr :: Constr
434+mimeListConstr = mkConstr mimeListDataType "MimeList" ["getMimeList"] Prefix
436+mimeListDataType :: DataType
437+mimeListDataType = mkDataType "Data.OpenApi.MimeList" [mimeListConstr]
439+instance Data MimeList where
440+ gunfold k z c = case constrIndex c of
441+ 1 -> k (z (MimeList . map fromString))
442+ _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type MimeList."
443+ toConstr (MimeList _) = mimeListConstr
444+ dataTypeOf _ = mimeListDataType
446+-- | Describes a single operation parameter.
447+-- A unique parameter is defined by a combination of a name and location.
449+ { -- | The name of the parameter.
450+ -- Parameter names are case sensitive.
453+ -- | A brief description of the parameter.
454+ -- This could contain examples of use.
455+ -- CommonMark syntax MAY be used for rich text representation.
456+ , _paramDescription :: Maybe Text
458+ -- | Determines whether this parameter is mandatory.
459+ -- If the parameter is in "path", this property is required and its value MUST be true.
460+ -- Otherwise, the property MAY be included and its default value is @False@.
461+ , _paramRequired :: Maybe Bool
463+ -- | Specifies that a parameter is deprecated and SHOULD be transitioned out of usage.
464+ -- Default value is @false@.
465+ , _paramDeprecated :: Maybe Bool
467+ -- | The location of the parameter.
468+ , _paramIn :: ParamLocation
470+ -- | Sets the ability to pass empty-valued parameters.
471+ -- This is valid only for 'ParamQuery' parameters and allows sending
472+ -- a parameter with an empty value. Default value is @false@.
473+ , _paramAllowEmptyValue :: Maybe Bool
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
482+ -- | Parameter schema.
483+ , _paramSchema :: Maybe (Referenced Schema)
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
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
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
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)
514+ -- _paramContent :: InsOrdHashMap MediaType MediaTypeObject
515+ -- should be singleton. mutually exclusive with _paramSchema.
516+ } deriving (Eq, Show, Generic, Data, Typeable)
518+data Example = Example
519+ { -- | Short description for the example.
520+ _exampleSummary :: Maybe Text
522+ -- | Long description for the example.
523+ -- CommonMark syntax MAY be used for rich text representation.
524+ , _exampleDescription :: Maybe Text
526+ -- | Embedded literal example.
527+ -- The '_exampleValue' field and '_exampleExternalValue' field are mutually exclusive.
529+ -- To represent examples of media types that cannot naturally represented in JSON or YAML,
530+ -- use a string value to contain the example, escaping where necessary.
531+ , _exampleValue :: Maybe Value
533+ -- | A URL that points to the literal example.
534+ -- This provides the capability to reference examples that cannot easily be included
535+ -- in JSON or YAML documents. The '_exampleValue' field
536+ -- and '_exampleExternalValue' field are mutually exclusive.
537+ , _exampleExternalValue :: Maybe URL
538+ } deriving (Eq, Show, Generic, Typeable, Data)
540+data ExpressionOrValue
543+ deriving (Eq, Show, Generic, Typeable, Data)
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.
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
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
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
566+ -- | A literal value or @{expression}@ to use as a request body when calling the target operation.
567+ , _linkRequestBody :: Maybe ExpressionOrValue
569+ -- | A description of the link.
570+ , _linkDescription :: Maybe Text
572+ -- | A server object to be used by the target operation.
573+ , _linkServer :: Maybe Server
574+ } deriving (Eq, Show, Generic, Typeable, Data)
576+-- | Items for @'OpenApiArray'@ schemas.
578+-- __Warning__: OpenAPI 3.0 does not support tuple arrays. However, OpenAPI 3.1 will, as
579+-- it will incorporate Json Schema mostly verbatim.
581+-- @'OpenApiItemsObject'@ should be used to specify homogenous array @'Schema'@s.
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)
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)
600+ = -- | Parameters that are appended to the URL.
601+ -- For example, in @/items?id=###@, the query parameter is @id@.
603+ -- | Custom headers that are expected as part of the request.
605+ -- | Used together with Path Templating, where the parameter value is actually part of the operation's URL.
606+ -- This does not include the host or base path of the API.
607+ -- For example, in @/items/{itemId}@, the path parameter is @itemId@.
609+ -- | Used to pass a specific cookie value to the API.
611+ deriving (Eq, Show, Generic, Data, Typeable)
615+type ParamName = Text
618+ { _schemaTitle :: Maybe Text
619+ , _schemaDescription :: Maybe Text
620+ , _schemaRequired :: [ParamName]
622+ , _schemaNullable :: Maybe Bool
623+ , _schemaAllOf :: Maybe [Referenced Schema]
624+ , _schemaOneOf :: Maybe [Referenced Schema]
625+ , _schemaNot :: Maybe (Referenced Schema)
626+ , _schemaAnyOf :: Maybe [Referenced Schema]
627+ , _schemaProperties :: InsOrdHashMap Text (Referenced Schema)
628+ , _schemaAdditionalProperties :: Maybe AdditionalProperties
630+ , _schemaDiscriminator :: Maybe Discriminator
631+ , _schemaReadOnly :: Maybe Bool
632+ , _schemaWriteOnly :: Maybe Bool
633+ , _schemaXml :: Maybe Xml
634+ , _schemaExternalDocs :: Maybe ExternalDocs
635+ , _schemaExample :: Maybe Value
636+ , _schemaDeprecated :: Maybe Bool
638+ , _schemaMaxProperties :: Maybe Integer
639+ , _schemaMinProperties :: Maybe Integer
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
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
663+ } deriving (Eq, Show, Generic, Data, Typeable)
665+-- | Regex pattern for @string@ type.
668+data Discriminator = Discriminator
669+ { -- | The name of the property in the payload that will hold the discriminator value.
670+ _discriminatorPropertyName :: Text
672+ -- | An object to hold mappings between payload values and schema names or references.
673+ , _discriminatorMapping :: InsOrdHashMap Text Text
674+ } deriving (Eq, Show, Generic, Data, Typeable)
676+-- | A @'Schema'@ with an optional name.
677+-- This name can be used in references.
678+data NamedSchema = NamedSchema
679+ { _namedSchemaName :: Maybe Text
680+ , _namedSchemaSchema :: Schema
681+ } deriving (Eq, Show, Generic, Data, Typeable)
684+ { -- | 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.
686+ -- When defined alongside type being array (outside the items),
687+ -- it will affect the wrapping element and only if wrapped is true.
688+ -- If wrapped is false, it will be ignored.
689+ _xmlName :: Maybe Text
691+ -- | The URL of the namespace definition.
692+ -- Value SHOULD be in the form of a URL.
693+ , _xmlNamespace :: Maybe Text
695+ -- | The prefix to be used for the name.
696+ , _xmlPrefix :: Maybe Text
698+ -- | Declares whether the property definition translates to an attribute instead of an element.
699+ -- Default value is @False@.
700+ , _xmlAttribute :: Maybe Bool
702+ -- | MAY be used only for an array definition.
703+ -- Signifies whether the array is wrapped
704+ -- (for example, @\<books\>\<book/\>\<book/\>\</books\>@)
705+ -- or unwrapped (@\<book/\>\<book/\>@).
706+ -- Default value is @False@.
707+ -- The definition takes effect only when defined alongside type being array (outside the items).
708+ , _xmlWrapped :: Maybe Bool
709+ } deriving (Eq, Show, Generic, Data, Typeable)
711+-- | A container for the expected responses of an operation.
712+-- The container maps a HTTP response code to the expected response.
713+-- It is not expected from the documentation to necessarily cover all possible HTTP response codes,
714+-- since they may not be known in advance.
715+-- However, it is expected from the documentation to cover a successful operation response and any known errors.
716+data Responses = Responses
717+ { -- | The documentation of responses other than the ones declared for specific HTTP response codes.
718+ -- It can be used to cover undeclared responses.
719+ _responsesDefault :: Maybe (Referenced Response)
721+ -- | Any HTTP status code can be used as the property name (one property per HTTP status code).
722+ -- Describes the expected response for those HTTP status codes.
723+ , _responsesResponses :: InsOrdHashMap HttpStatusCode (Referenced Response)
724+ } deriving (Eq, Show, Generic, Data, Typeable)
726+type HttpStatusCode = Int
728+-- | Describes a single response from an API Operation.
729+data Response = Response
730+ { -- | A short description of the response.
731+ -- [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
732+ _responseDescription :: Text
734+ -- | A map containing descriptions of potential response payloads.
735+ -- The key is a media type or media type range and the value describes it.
736+ -- 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
740+ -- | Maps a header name to its definition.
741+ , _responseHeaders :: InsOrdHashMap HeaderName (Referenced Header)
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)
747+ } deriving (Eq, Show, Generic, Data, Typeable)
749+instance IsString Response where
750+ fromString s = Response (fromString s) mempty mempty mempty
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)
760+type HeaderName = Text
762+-- | Header fields have the same meaning as for 'Param'.
764+-- Style is always treated as 'StyleSimple', as it is the only value allowed for headers.
766+ { -- | A short description of the header.
767+ _headerDescription :: Maybe HeaderName
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)
776+ , _headerSchema :: Maybe (Referenced Schema)
777+ } deriving (Eq, Show, Generic, Data, Typeable)
779+-- | The location of the API key.
784+ deriving (Eq, Show, Generic, Data, Typeable)
786+data ApiKeyParams = ApiKeyParams
787+ { -- | The name of the header or query parameter to be used.
790+ -- | The location of the API key.
791+ , _apiKeyIn :: ApiKeyLocation
792+ } deriving (Eq, Show, Generic, Data, Typeable)
794+-- | The authorization URL to be used for OAuth2 flow. This SHOULD be in the form of a URL.
795+type AuthorizationURL = Text
797+-- | The token URL to be used for OAuth2 flow. This SHOULD be in the form of a URL.
800+newtype OAuth2ImplicitFlow
801+ = OAuth2ImplicitFlow {_oAuth2ImplicitFlowAuthorizationUrl :: AuthorizationURL}
802+ deriving (Eq, Show, Generic, Data, Typeable)
804+newtype OAuth2PasswordFlow
805+ = OAuth2PasswordFlow {_oAuth2PasswordFlowTokenUrl :: TokenURL}
806+ deriving (Eq, Show, Generic, Data, Typeable)
808+newtype OAuth2ClientCredentialsFlow
809+ = OAuth2ClientCredentialsFlow {_oAuth2ClientCredentialsFlowTokenUrl :: TokenURL}
810+ deriving (Eq, Show, Generic, Data, Typeable)
812+data OAuth2AuthorizationCodeFlow = OAuth2AuthorizationCodeFlow
813+ { _oAuth2AuthorizationCodeFlowAuthorizationUrl :: AuthorizationURL
814+ , _oAuth2AuthorizationCodeFlowTokenUrl :: TokenURL
815+ } deriving (Eq, Show, Generic, Data, Typeable)
817+data OAuth2Flow p = OAuth2Flow
818+ { _oAuth2Params :: p
820+ -- | The URL to be used for obtaining refresh tokens.
821+ , _oAath2RefreshUrl :: Maybe URL
823+ -- | The available scopes for the OAuth2 security scheme.
824+ -- A map between the scope name and a short description for it.
825+ -- The map MAY be empty.
826+ , _oAuth2Scopes :: InsOrdHashMap Text Text
827+ } deriving (Eq, Show, Generic, Data, Typeable)
829+data OAuth2Flows = OAuth2Flows
830+ { -- | Configuration for the OAuth Implicit flow
831+ _oAuth2FlowsImplicit :: Maybe (OAuth2Flow OAuth2ImplicitFlow)
833+ -- | Configuration for the OAuth Resource Owner Password flow
834+ , _oAuth2FlowsPassword :: Maybe (OAuth2Flow OAuth2PasswordFlow)
836+ -- | Configuration for the OAuth Client Credentials flow
837+ , _oAuth2FlowsClientCredentials :: Maybe (OAuth2Flow OAuth2ClientCredentialsFlow)
839+ -- | Configuration for the OAuth Authorization Code flow
840+ , _oAuth2FlowsAuthorizationCode :: Maybe (OAuth2Flow OAuth2AuthorizationCodeFlow)
841+ } deriving (Eq, Show, Generic, Data, Typeable)
843+type BearerFormat = Text
846+ = HttpSchemeBearer (Maybe BearerFormat)
848+ | HttpSchemeCustom Text
849+ deriving (Eq, Show, Generic, Data, Typeable)
853+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer Nothing))
855+-- "scheme": "bearer",
859+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer (Just "jwt")))
861+-- "bearerFormat": "jwt",
862+-- "scheme": "bearer",
866+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp HttpSchemeBasic)
868+-- "scheme": "basic",
872+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeCustom "CANARY"))
874+-- "scheme": "CANARY",
878+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeApiKey (ApiKeyParams "id" ApiKeyCookie))
885+data SecuritySchemeType
886+ = SecuritySchemeHttp HttpSchemeType
887+ | SecuritySchemeApiKey ApiKeyParams
888+ | SecuritySchemeOAuth2 OAuth2Flows
889+ | SecuritySchemeOpenIdConnect URL
890+ deriving (Eq, Show, Generic, Data, Typeable)
892+data SecurityScheme = SecurityScheme
893+ { -- | The type of the security scheme.
894+ _securitySchemeType :: SecuritySchemeType
896+ -- | A short description for security scheme.
897+ , _securitySchemeDescription :: Maybe Text
898+ } deriving (Eq, Show, Generic, Data, Typeable)
900+newtype SecurityDefinitions
901+ = SecurityDefinitions (Definitions SecurityScheme)
902+ deriving (Eq, Show, Generic, Data, Typeable)
904+-- | Lists the required security schemes to execute this operation.
905+-- The object can have multiple security schemes declared in it which are all required
906+-- (that is, there is a logical AND between the schemes).
907+newtype SecurityRequirement = SecurityRequirement
908+ { getSecurityRequirement :: InsOrdHashMap Text [Text]
909+ } deriving (Eq, Read, Show, Semigroup, Monoid, ToJSON, FromJSON, Data, Typeable)
914+-- | Allows adding meta data to a single tag that is used by @Operation@.
915+-- It is not mandatory to have a @Tag@ per tag used there.
917+ { -- | The name of the tag.
920+ -- | A short description for the tag.
921+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
922+ , _tagDescription :: Maybe Text
924+ -- | Additional external documentation for this tag.
925+ , _tagExternalDocs :: Maybe ExternalDocs
926+ } deriving (Eq, Ord, Show, Generic, Data, Typeable)
928+instance Hashable Tag
930+instance IsString Tag where
931+ fromString s = Tag (fromString s) Nothing Nothing
933+-- | Allows referencing an external resource for extended documentation.
934+data ExternalDocs = ExternalDocs
935+ { -- | A short description of the target documentation.
936+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
937+ _externalDocsDescription :: Maybe Text
939+ -- | The URL for the target documentation.
940+ , _externalDocsUrl :: URL
941+ } deriving (Eq, Ord, Show, Generic, Data, Typeable)
943+instance Hashable ExternalDocs
945+-- | A simple object to allow referencing other definitions in the specification.
946+-- It can be used to reference parameters and responses that are defined at the top level for reuse.
947+newtype Reference = Reference { getReference :: Text }
948+ deriving (Eq, Show, Data, Typeable)
953+ deriving (Eq, Show, Functor, Data, Typeable)
955+instance IsString a => IsString (Referenced a) where
956+ fromString = Inline . fromString
958+newtype URL = URL { getUrl :: Text } deriving (Eq, Ord, Show, Hashable, ToJSON, FromJSON, Data, Typeable)
960+data AdditionalProperties
961+ = AdditionalPropertiesAllowed Bool
962+ | AdditionalPropertiesSchema (Referenced Schema)
963+ deriving (Eq, Show, Data, Typeable)
965+-------------------------------------------------------------------------------
967+-------------------------------------------------------------------------------
969+deriveGeneric ''Server
970+deriveGeneric ''Components
971+deriveGeneric ''Header
972+deriveGeneric ''OAuth2Flow
973+deriveGeneric ''OAuth2Flows
974+deriveGeneric ''Operation
975+deriveGeneric ''Param
976+deriveGeneric ''PathItem
977+deriveGeneric ''Response
978+deriveGeneric ''RequestBody
979+deriveGeneric ''MediaTypeObject
980+deriveGeneric ''Responses
981+deriveGeneric ''SecurityScheme
982+deriveGeneric ''Schema
983+deriveGeneric ''OpenApi
984+deriveGeneric ''Example
985+deriveGeneric ''Encoding
988+-- =======================================================================
990+-- =======================================================================
992+instance Semigroup OpenApi where
993+ (<>) = genericMappend
994+instance Monoid OpenApi where
995+ mempty = genericMempty
998+instance Semigroup Info where
999+ (<>) = genericMappend
1000+instance Monoid Info where
1001+ mempty = genericMempty
1004+instance Semigroup Contact where
1005+ (<>) = genericMappend
1006+instance Monoid Contact where
1007+ mempty = genericMempty
1010+instance Semigroup Components where
1011+ (<>) = genericMappend
1012+instance Monoid Components where
1013+ mempty = genericMempty
1016+instance Semigroup PathItem where
1017+ (<>) = genericMappend
1018+instance Monoid PathItem where
1019+ mempty = genericMempty
1022+instance Semigroup Schema where
1023+ (<>) = genericMappend
1024+instance Monoid Schema where
1025+ mempty = genericMempty
1028+instance Semigroup Param where
1029+ (<>) = genericMappend
1030+instance Monoid Param where
1031+ mempty = genericMempty
1034+instance Semigroup Header where
1035+ (<>) = genericMappend
1036+instance Monoid Header where
1037+ mempty = genericMempty
1040+instance Semigroup Responses where
1041+ (<>) = genericMappend
1042+instance Monoid Responses where
1043+ mempty = genericMempty
1046+instance Semigroup Response where
1047+ (<>) = genericMappend
1048+instance Monoid Response where
1049+ mempty = genericMempty
1052+instance Semigroup MediaTypeObject where
1053+ (<>) = genericMappend
1054+instance Monoid MediaTypeObject where
1055+ mempty = genericMempty
1058+instance Semigroup Encoding where
1059+ (<>) = genericMappend
1060+instance Monoid Encoding where
1061+ mempty = genericMempty
1064+instance Semigroup ExternalDocs where
1065+ (<>) = genericMappend
1066+instance Monoid ExternalDocs where
1067+ mempty = genericMempty
1070+instance Semigroup Operation where
1071+ (<>) = genericMappend
1072+instance Monoid Operation where
1073+ mempty = genericMempty
1076+instance Semigroup (OAuth2Flow p) where
1077+ l@OAuth2Flow{ _oAath2RefreshUrl = lUrl, _oAuth2Scopes = lScopes }
1078+ <> OAuth2Flow { _oAath2RefreshUrl = rUrl, _oAuth2Scopes = rScopes } =
1079+ l { _oAath2RefreshUrl = swaggerMappend lUrl rUrl, _oAuth2Scopes = lScopes <> rScopes }
1081+-- swaggerMappend has First-like semantics, and here we need mappend'ing under Maybes.
1082+instance Semigroup OAuth2Flows where
1083+ l <> r = OAuth2Flows
1084+ { _oAuth2FlowsImplicit = _oAuth2FlowsImplicit l <> _oAuth2FlowsImplicit r
1085+ , _oAuth2FlowsPassword = _oAuth2FlowsPassword l <> _oAuth2FlowsPassword r
1086+ , _oAuth2FlowsClientCredentials = _oAuth2FlowsClientCredentials l <> _oAuth2FlowsClientCredentials r
1087+ , _oAuth2FlowsAuthorizationCode = _oAuth2FlowsAuthorizationCode l <> _oAuth2FlowsAuthorizationCode r
1090+instance Monoid OAuth2Flows where
1091+ mempty = genericMempty
1094+instance Semigroup SecurityScheme where
1095+ SecurityScheme (SecuritySchemeOAuth2 lFlows) lDesc
1096+ <> SecurityScheme (SecuritySchemeOAuth2 rFlows) rDesc =
1097+ SecurityScheme (SecuritySchemeOAuth2 $ lFlows <> rFlows) (swaggerMappend lDesc rDesc)
1100+instance Semigroup SecurityDefinitions where
1101+ (SecurityDefinitions sd1) <> (SecurityDefinitions sd2) =
1102+ SecurityDefinitions $ InsOrdHashMap.unionWith (<>) sd1 sd2
1104+instance Monoid SecurityDefinitions where
1105+ mempty = SecurityDefinitions InsOrdHashMap.empty
1108+instance Semigroup RequestBody where
1109+ (<>) = genericMappend
1110+instance Monoid RequestBody where
1111+ mempty = genericMempty
1114+-- =======================================================================
1115+-- SwaggerMonoid helper instances
1116+-- =======================================================================
1118+instance SwaggerMonoid Info
1119+instance SwaggerMonoid Components
1120+instance SwaggerMonoid PathItem
1121+instance SwaggerMonoid Schema
1122+instance SwaggerMonoid Param
1123+instance SwaggerMonoid Responses
1124+instance SwaggerMonoid Response
1125+instance SwaggerMonoid ExternalDocs
1126+instance SwaggerMonoid Operation
1127+instance (Eq a, Hashable a) => SwaggerMonoid (InsOrdHashSet a)
1128+instance SwaggerMonoid SecurityDefinitions
1130+instance SwaggerMonoid MimeList
1131+deriving instance SwaggerMonoid URL
1133+instance SwaggerMonoid OpenApiType where
1134+ swaggerMempty = OpenApiString
1135+ swaggerMappend _ y = y
1137+instance SwaggerMonoid ParamLocation where
1138+ swaggerMempty = ParamQuery
1139+ swaggerMappend _ y = y
1141+instance {-# OVERLAPPING #-} SwaggerMonoid (InsOrdHashMap FilePath PathItem) where
1142+ swaggerMempty = InsOrdHashMap.empty
1143+ swaggerMappend = InsOrdHashMap.unionWith mappend
1145+instance Monoid a => SwaggerMonoid (Referenced a) where
1146+ swaggerMempty = Inline mempty
1147+ swaggerMappend (Inline x) (Inline y) = Inline (mappend x y)
1148+ swaggerMappend _ y = y
1150+-- =======================================================================
1151+-- Simple Generic-based ToJSON instances
1152+-- =======================================================================
1154+instance ToJSON Style where
1155+ toJSON = genericToJSON (jsonPrefix "Style")
1157+instance ToJSON OpenApiType where
1158+ toJSON = genericToJSON (jsonPrefix "Swagger")
1160+instance ToJSON ParamLocation where
1161+ toJSON = genericToJSON (jsonPrefix "Param")
1163+instance ToJSON Info where
1164+ toJSON = genericToJSON (jsonPrefix "Info")
1166+instance ToJSON Contact where
1167+ toJSON = genericToJSON (jsonPrefix "Contact")
1169+instance ToJSON License where
1170+ toJSON = genericToJSON (jsonPrefix "License")
1172+instance ToJSON ServerVariable where
1173+ toJSON = genericToJSON (jsonPrefix "ServerVariable")
1175+instance ToJSON ApiKeyLocation where
1176+ toJSON = genericToJSON (jsonPrefix "ApiKey")
1178+instance ToJSON ApiKeyParams where
1179+ toJSON = genericToJSON (jsonPrefix "apiKey")
1181+instance ToJSON Tag where
1182+ toJSON = genericToJSON (jsonPrefix "Tag")
1184+instance ToJSON ExternalDocs where
1185+ toJSON = genericToJSON (jsonPrefix "ExternalDocs")
1187+instance ToJSON Xml where
1188+ toJSON = genericToJSON (jsonPrefix "Xml")
1190+instance ToJSON Discriminator where
1191+ toJSON = genericToJSON (jsonPrefix "Discriminator")
1193+instance ToJSON OAuth2ImplicitFlow where
1194+ toJSON = genericToJSON (jsonPrefix "OAuth2ImplicitFlow")
1196+instance ToJSON OAuth2PasswordFlow where
1197+ toJSON = genericToJSON (jsonPrefix "OAuth2PasswordFlow")
1199+instance ToJSON OAuth2ClientCredentialsFlow where
1200+ toJSON = genericToJSON (jsonPrefix "OAuth2ClientCredentialsFlow")
1202+instance ToJSON OAuth2AuthorizationCodeFlow where
1203+ toJSON = genericToJSON (jsonPrefix "OAuth2AuthorizationCodeFlow")
1205+-- =======================================================================
1206+-- Simple Generic-based FromJSON instances
1207+-- =======================================================================
1209+instance FromJSON Style where
1210+ parseJSON = genericParseJSON (jsonPrefix "Style")
1212+instance FromJSON OpenApiType where
1213+ parseJSON = genericParseJSON (jsonPrefix "Swagger")
1215+instance FromJSON ParamLocation where
1216+ parseJSON = genericParseJSON (jsonPrefix "Param")
1218+instance FromJSON Info where
1219+ parseJSON = genericParseJSON (jsonPrefix "Info")
1221+instance FromJSON Contact where
1222+ parseJSON = genericParseJSON (jsonPrefix "Contact")
1224+instance FromJSON License where
1225+ parseJSON = genericParseJSON (jsonPrefix "License")
1227+instance FromJSON ServerVariable where
1228+ parseJSON = genericParseJSON (jsonPrefix "ServerVariable")
1230+instance FromJSON ApiKeyLocation where
1231+ parseJSON = genericParseJSON (jsonPrefix "ApiKey")
1233+instance FromJSON ApiKeyParams where
1234+ parseJSON = genericParseJSON (jsonPrefix "apiKey")
1236+instance FromJSON Tag where
1237+ parseJSON = genericParseJSON (jsonPrefix "Tag")
1239+instance FromJSON ExternalDocs where
1240+ parseJSON = genericParseJSON (jsonPrefix "ExternalDocs")
1242+instance FromJSON Discriminator where
1243+ parseJSON = genericParseJSON (jsonPrefix "Discriminator")
1245+instance FromJSON OAuth2ImplicitFlow where
1246+ parseJSON = genericParseJSON (jsonPrefix "OAuth2ImplicitFlow")
1248+instance FromJSON OAuth2PasswordFlow where
1249+ parseJSON = genericParseJSON (jsonPrefix "OAuth2PasswordFlow")
1251+instance FromJSON OAuth2ClientCredentialsFlow where
1252+ parseJSON = genericParseJSON (jsonPrefix "OAuth2ClientCredentialsFlow")
1254+instance FromJSON OAuth2AuthorizationCodeFlow where
1255+ parseJSON = genericParseJSON (jsonPrefix "OAuth2AuthorizationCodeFlow")
1257+-- =======================================================================
1258+-- Manual ToJSON instances
1259+-- =======================================================================
1261+instance ToJSON MediaType where
1262+ toJSON = toJSON . show
1263+ toEncoding = toEncoding . show
1265+instance ToJSONKey MediaType where
1266+ toJSONKey = JSON.toJSONKeyText (Text.pack . show)
1268+instance (Eq p, ToJSON p, AesonDefaultValue p) => ToJSON (OAuth2Flow p) where
1269+ toJSON = sopSwaggerGenericToJSON
1270+ toEncoding = sopSwaggerGenericToEncoding
1272+instance ToJSON OAuth2Flows where
1273+ toJSON = sopSwaggerGenericToJSON
1274+ toEncoding = sopSwaggerGenericToEncoding
1276+instance 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
1283+ object [ "type" .= ("http" :: Text)
1284+ , "scheme" .= ("basic" :: Text)
1286+ HttpSchemeCustom t ->
1287+ object [ "type" .= ("http" :: Text)
1290+ toJSON (SecuritySchemeApiKey params)
1292+ <+> object [ "type" .= ("apiKey" :: Text) ]
1293+ toJSON (SecuritySchemeOAuth2 params) = object
1294+ [ "type" .= ("oauth2" :: Text)
1295+ , "flows" .= toJSON params
1297+ toJSON (SecuritySchemeOpenIdConnect url) = object
1298+ [ "type" .= ("openIdConnect" :: Text)
1299+ , "openIdConnectUrl" .= url
1302+instance ToJSON OpenApi where
1303+ toJSON a = sopSwaggerGenericToJSON a &
1304+ if InsOrdHashMap.null (_openApiPaths a)
1305+ then (<+> object ["paths" .= object []])
1307+ toEncoding = sopSwaggerGenericToEncoding
1309+instance ToJSON Server where
1310+ toJSON = sopSwaggerGenericToJSON
1311+ toEncoding = sopSwaggerGenericToEncoding
1313+instance ToJSON SecurityScheme where
1314+ toJSON = sopSwaggerGenericToJSON
1315+ toEncoding = sopSwaggerGenericToEncoding
1317+instance ToJSON Schema where
1318+ toJSON = sopSwaggerGenericToJSONWithOpts $
1319+ mkSwaggerAesonOptions "schema" & saoSubObject ?~ "items"
1321+instance ToJSON Header where
1322+ toJSON = sopSwaggerGenericToJSON
1323+ toEncoding = sopSwaggerGenericToEncoding
1325+-- | As for nullary schema for 0-arity type constructors, see
1326+-- <https://github.com/GetShopTV/swagger2/issues/167>.
1328+-- >>> BSL.putStrLn $ encodePretty (OpenApiItemsArray [])
1335+instance ToJSON OpenApiItems where
1336+ toJSON (OpenApiItemsObject x) = object [ "items" .= x ]
1337+ toJSON (OpenApiItemsArray []) = object
1338+ [ "items" .= object []
1339+ , "maxItems" .= (0 :: Int)
1340+ , "example" .= Array mempty
1342+ toJSON (OpenApiItemsArray x) = object [ "items" .= x ]
1344+instance ToJSON Components where
1345+ toJSON = sopSwaggerGenericToJSON
1346+ toEncoding = sopSwaggerGenericToEncoding
1348+instance ToJSON MimeList where
1349+ toJSON (MimeList xs) = toJSON (map show xs)
1351+instance ToJSON Param where
1352+ toJSON = sopSwaggerGenericToJSON
1353+ toEncoding = sopSwaggerGenericToEncoding
1355+instance ToJSON Responses where
1356+ toJSON = sopSwaggerGenericToJSON
1357+ toEncoding = sopSwaggerGenericToEncoding
1359+instance ToJSON Response where
1360+ toJSON = sopSwaggerGenericToJSON
1361+ toEncoding = sopSwaggerGenericToEncoding
1363+instance ToJSON Operation where
1364+ toJSON = sopSwaggerGenericToJSON
1365+ toEncoding = sopSwaggerGenericToEncoding
1367+instance ToJSON PathItem where
1368+ toJSON = sopSwaggerGenericToJSON
1369+ toEncoding = sopSwaggerGenericToEncoding
1371+instance ToJSON RequestBody where
1372+ toJSON = sopSwaggerGenericToJSON
1373+ toEncoding = sopSwaggerGenericToEncoding
1375+instance ToJSON MediaTypeObject where
1376+ toJSON = sopSwaggerGenericToJSON
1377+ toEncoding = sopSwaggerGenericToEncoding
1379+instance ToJSON Example where
1380+ toJSON = sopSwaggerGenericToJSON
1381+ toEncoding = sopSwaggerGenericToEncoding
1383+instance ToJSON Encoding where
1384+ toJSON = sopSwaggerGenericToJSON
1385+ toEncoding = sopSwaggerGenericToEncoding
1387+instance ToJSON Link where
1388+ toJSON = sopSwaggerGenericToJSON
1389+ toEncoding = sopSwaggerGenericToEncoding
1391+instance ToJSON SecurityDefinitions where
1392+ toJSON (SecurityDefinitions sd) = toJSON sd
1394+instance ToJSON Reference where
1395+ toJSON (Reference ref) = object [ "$ref" .= ref ]
1397+referencedToJSON :: ToJSON a => Text -> Referenced a -> Value
1398+referencedToJSON prefix (Ref (Reference ref)) = object [ "$ref" .= (prefix <> ref) ]
1399+referencedToJSON _ (Inline x) = toJSON x
1401+instance ToJSON (Referenced Schema) where toJSON = referencedToJSON "#/components/schemas/"
1402+instance ToJSON (Referenced Param) where toJSON = referencedToJSON "#/components/parameters/"
1403+instance ToJSON (Referenced Response) where toJSON = referencedToJSON "#/components/responses/"
1404+instance ToJSON (Referenced RequestBody) where toJSON = referencedToJSON "#/components/requestBodies/"
1405+instance ToJSON (Referenced Example) where toJSON = referencedToJSON "#/components/examples/"
1406+instance 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/"
1410+instance ToJSON AdditionalProperties where
1411+ toJSON (AdditionalPropertiesAllowed b) = toJSON b
1412+ toJSON (AdditionalPropertiesSchema s) = toJSON s
1414+instance ToJSON ExpressionOrValue where
1415+ toJSON (Expression expr) = toJSON expr
1416+ toJSON (Value val) = toJSON val
1418+instance ToJSON Callback where
1419+ toJSON (Callback ps) = toJSON ps
1421+-- =======================================================================
1422+-- Manual FromJSON instances
1423+-- =======================================================================
1425+instance FromJSON MediaType where
1426+ parseJSON = withText "MediaType" $ \str ->
1427+ maybe (fail $ "Invalid media type literal " <> Text.unpack str) pure $ parseAccept $ encodeUtf8 str
1429+instance FromJSONKey MediaType where
1430+ fromJSONKey = FromJSONKeyTextParser (parseJSON . String)
1432+instance (Eq p, FromJSON p, AesonDefaultValue p) => FromJSON (OAuth2Flow p) where
1433+ parseJSON = sopSwaggerGenericParseJSON
1435+instance FromJSON OAuth2Flows where
1436+ parseJSON = sopSwaggerGenericParseJSON
1438+instance FromJSON SecuritySchemeType where
1439+ parseJSON js@(Object o) = do
1440+ (t :: Text) <- o .: "type"
1443+ scheme <- o .: "scheme"
1444+ SecuritySchemeHttp <$> case scheme of
1445+ "bearer" -> HttpSchemeBearer <$> (o .:! "bearerFormat")
1446+ "basic" -> pure HttpSchemeBasic
1447+ t -> pure $ HttpSchemeCustom t
1448+ "apiKey" -> SecuritySchemeApiKey <$> parseJSON js
1449+ "oauth2" -> SecuritySchemeOAuth2 <$> (o .: "flows")
1450+ "openIdConnect" -> SecuritySchemeOpenIdConnect <$> (o .: "openIdConnectUrl")
1452+ parseJSON _ = empty
1454+instance FromJSON OpenApi where
1455+ parseJSON = sopSwaggerGenericParseJSON
1457+instance FromJSON Server where
1458+ parseJSON = sopSwaggerGenericParseJSON
1460+instance FromJSON SecurityScheme where
1461+ parseJSON = sopSwaggerGenericParseJSON
1463+instance FromJSON Schema where
1464+ parseJSON = fmap nullaryCleanup . sopSwaggerGenericParseJSON
1465+ where nullaryCleanup :: Schema -> Schema
1467+ if _schemaItems s == Just (OpenApiItemsArray [])
1468+ then s { _schemaExample = Nothing
1469+ , _schemaMaxItems = Nothing
1473+instance FromJSON Header where
1474+ parseJSON = sopSwaggerGenericParseJSON
1476+instance FromJSON OpenApiItems where
1477+ parseJSON js@(Object obj)
1478+ | null obj = pure $ OpenApiItemsArray [] -- Nullary schema.
1479+ | otherwise = OpenApiItemsObject <$> parseJSON js
1480+ parseJSON js@(Array _) = OpenApiItemsArray <$> parseJSON js
1481+ parseJSON _ = empty
1483+instance FromJSON Components where
1484+ parseJSON = sopSwaggerGenericParseJSON
1486+instance FromJSON MimeList where
1487+ parseJSON js = MimeList . map fromString <$> parseJSON js
1489+instance FromJSON Param where
1490+ parseJSON = sopSwaggerGenericParseJSON
1492+instance FromJSON Responses where
1493+ parseJSON (Object o) = Responses
1494+ <$> o .:? "default"
1495+ <*> parseJSON (Object (deleteKey "default" o))
1496+ parseJSON _ = empty
1498+instance FromJSON Example where
1499+ parseJSON = sopSwaggerGenericParseJSON
1501+instance FromJSON Response where
1502+ parseJSON = sopSwaggerGenericParseJSON
1504+instance FromJSON Operation where
1505+ parseJSON = sopSwaggerGenericParseJSON
1507+instance FromJSON PathItem where
1508+ parseJSON = sopSwaggerGenericParseJSON
1510+instance FromJSON SecurityDefinitions where
1511+ parseJSON js = SecurityDefinitions <$> parseJSON js
1513+instance FromJSON RequestBody where
1514+ parseJSON = sopSwaggerGenericParseJSON
1516+instance FromJSON MediaTypeObject where
1517+ parseJSON = sopSwaggerGenericParseJSON
1519+instance FromJSON Encoding where
1520+ parseJSON = sopSwaggerGenericParseJSON
1522+instance FromJSON Link where
1523+ parseJSON = sopSwaggerGenericParseJSON
1525+instance FromJSON Reference where
1526+ parseJSON (Object o) = Reference <$> o .: "$ref"
1527+ parseJSON _ = empty
1529+referencedParseJSON :: FromJSON a => Text -> Value -> JSON.Parser (Referenced a)
1530+referencedParseJSON prefix js@(Object o) = do
1533+ Nothing -> Inline <$> parseJSON js
1534+ Just s -> Ref <$> parseRef s
1537+ case Text.stripPrefix prefix s of
1538+ Nothing -> fail $ "expected $ref of the form \"" <> Text.unpack prefix <> "*\", but got " <> show s
1539+ Just suffix -> pure (Reference suffix)
1540+referencedParseJSON _ _ = fail "referenceParseJSON: not an object"
1542+instance FromJSON (Referenced Schema) where parseJSON = referencedParseJSON "#/components/schemas/"
1543+instance FromJSON (Referenced Param) where parseJSON = referencedParseJSON "#/components/parameters/"
1544+instance FromJSON (Referenced Response) where parseJSON = referencedParseJSON "#/components/responses/"
1545+instance FromJSON (Referenced RequestBody) where parseJSON = referencedParseJSON "#/components/requestBodies/"
1546+instance FromJSON (Referenced Example) where parseJSON = referencedParseJSON "#/components/examples/"
1547+instance 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/"
1551+instance FromJSON Xml where
1552+ parseJSON = genericParseJSON (jsonPrefix "xml")
1554+instance FromJSON AdditionalProperties where
1555+ parseJSON (Bool b) = pure $ AdditionalPropertiesAllowed b
1556+ parseJSON js = AdditionalPropertiesSchema <$> parseJSON js
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
1563+instance FromJSON Callback where
1564+ parseJSON = fmap Callback . parseJSON
1566+instance HasSwaggerAesonOptions Server where
1567+ swaggerAesonOptions _ = mkSwaggerAesonOptions "server"
1568+instance HasSwaggerAesonOptions Components where
1569+ swaggerAesonOptions _ = mkSwaggerAesonOptions "components"
1570+instance HasSwaggerAesonOptions Header where
1571+ swaggerAesonOptions _ = mkSwaggerAesonOptions "header"
1572+instance AesonDefaultValue p => HasSwaggerAesonOptions (OAuth2Flow p) where
1573+ swaggerAesonOptions _ = mkSwaggerAesonOptions "oauth2" & saoSubObject ?~ "params"
1574+instance HasSwaggerAesonOptions OAuth2Flows where
1575+ swaggerAesonOptions _ = mkSwaggerAesonOptions "oauth2Flows"
1576+instance HasSwaggerAesonOptions Operation where
1577+ swaggerAesonOptions _ = mkSwaggerAesonOptions "operation"
1578+instance HasSwaggerAesonOptions Param where
1579+ swaggerAesonOptions _ = mkSwaggerAesonOptions "param"
1580+instance HasSwaggerAesonOptions PathItem where
1581+ swaggerAesonOptions _ = mkSwaggerAesonOptions "pathItem"
1582+instance HasSwaggerAesonOptions Response where
1583+ swaggerAesonOptions _ = mkSwaggerAesonOptions "response"
1584+instance HasSwaggerAesonOptions RequestBody where
1585+ swaggerAesonOptions _ = mkSwaggerAesonOptions "requestBody"
1586+instance HasSwaggerAesonOptions MediaTypeObject where
1587+ swaggerAesonOptions _ = mkSwaggerAesonOptions "mediaTypeObject"
1588+instance HasSwaggerAesonOptions Responses where
1589+ swaggerAesonOptions _ = mkSwaggerAesonOptions "responses" & saoSubObject ?~ "responses"
1590+instance HasSwaggerAesonOptions SecurityScheme where
1591+ swaggerAesonOptions _ = mkSwaggerAesonOptions "securityScheme" & saoSubObject ?~ "type"
1592+instance HasSwaggerAesonOptions Schema where
1593+ swaggerAesonOptions _ = mkSwaggerAesonOptions "schema" & saoSubObject ?~ "paramSchema"
1594+instance HasSwaggerAesonOptions OpenApi where
1595+ swaggerAesonOptions _ = mkSwaggerAesonOptions "swagger" & saoAdditionalPairs .~ [("openapi", "3.0.0")]
1596+instance HasSwaggerAesonOptions Example where
1597+ swaggerAesonOptions _ = mkSwaggerAesonOptions "example"
1598+instance HasSwaggerAesonOptions Encoding where
1599+ swaggerAesonOptions _ = mkSwaggerAesonOptions "encoding"
1601+instance HasSwaggerAesonOptions Link where
1602+ swaggerAesonOptions _ = mkSwaggerAesonOptions "link"
1604+instance AesonDefaultValue Server
1605+instance AesonDefaultValue Components
1606+instance AesonDefaultValue OAuth2ImplicitFlow
1607+instance AesonDefaultValue OAuth2PasswordFlow
1608+instance AesonDefaultValue OAuth2ClientCredentialsFlow
1609+instance AesonDefaultValue OAuth2AuthorizationCodeFlow
1610+instance AesonDefaultValue p => AesonDefaultValue (OAuth2Flow p)
1611+instance AesonDefaultValue Responses
1612+instance AesonDefaultValue SecuritySchemeType
1613+instance AesonDefaultValue OpenApiType
1614+instance AesonDefaultValue MimeList where defaultValue = Just mempty
1615+instance AesonDefaultValue Info
1616+instance AesonDefaultValue ParamLocation
1617+instance AesonDefaultValue Link
1618+instance AesonDefaultValue SecurityDefinitions where
1619+ defaultValue = Just mempty