swagger2-2.0.2: Swagger 2.0 data model

MaintainerNickolay Kudasov <nickolay@getshoptv.com>
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Data.Swagger.Schema

Contents

Description

Types and functions for working with Swagger schema.

Synopsis

Encoding

class ToSchema a where Source

Convert a type into Schema.

An example type and instance:

{-# LANGUAGE OverloadedStrings #-}   -- allows to write Text literals
{-# LANGUAGE OverloadedLists #-}     -- allows to write Map and HashMap as lists

import Control.Lens

data Coord = Coord { x :: Double, y :: Double }

instance ToSchema Coord where
  declareNamedSchema = pure (Just "Coord", schema)
   where
     schema = mempty
       & type_ .~ SwaggerObject
       & properties .~
           [ ("x", toSchemaRef (Proxy :: Proxy Double))
           , ("y", toSchemaRef (Proxy :: Proxy Double))
           ]
       & required .~ [ "x", "y" ]

Instead of manually writing your ToSchema instance you can use a default generic implementation of declareNamedSchema.

To do that, simply add deriving Generic clause to your datatype and declare a ToSchema instance for your datatype without giving definition for declareNamedSchema.

For instance, the previous example can be simplified into this:

{-# LANGUAGE DeriveGeneric #-}

import GHC.Generics (Generic)

data Coord = Coord { x :: Double, y :: Double } deriving Generic

instance ToSchema Coord

Minimal complete definition

Nothing

Methods

declareNamedSchema :: proxy a -> Declare (Definitions Schema) NamedSchema Source

Convert a type into an optionally named schema together with all used definitions. Note that the schema itself is included in definitions only if it is recursive (and thus needs its definition in scope).

Instances

ToSchema Bool Source 
ToSchema Char Source 
ToSchema Double Source 
ToSchema Float Source 
ToSchema Int Source 
ToSchema Int8 Source 
ToSchema Int16 Source 
ToSchema Int32 Source 
ToSchema Int64 Source 
ToSchema Integer Source 
ToSchema Word Source 
ToSchema Word8 Source 
ToSchema Word16 Source 
ToSchema Word32 Source 
ToSchema Word64 Source 
ToSchema String Source 
ToSchema () Source 
ToSchema Scientific Source 
ToSchema Text Source 
ToSchema UTCTime Source
>>> toSchema (Proxy :: Proxy UTCTime) ^. format
Just "yyyy-mm-ddThh:MM:ssZ"
ToSchema Text Source 
ToSchema All Source 
ToSchema Any Source 
ToSchema IntSet Source 
ToSchema LocalTime Source
>>> toSchema (Proxy :: Proxy LocalTime) ^. format
Just "yyyy-mm-ddThh:MM:ss"
ToSchema ZonedTime Source

Format "date" corresponds to yyyy-mm-ddThh:MM:ss(Z|+hh:MM) format.

ToSchema NominalDiffTime Source 
ToSchema Day Source

Format "date" corresponds to yyyy-mm-dd format.

ToSchema a => ToSchema [a] Source 
ToSchema a => ToSchema (Maybe a) Source 
ToSchema a => ToSchema (Dual a) Source 
ToSchema a => ToSchema (Sum a) Source 
ToSchema a => ToSchema (Product a) Source 
ToSchema a => ToSchema (First a) Source 
ToSchema a => ToSchema (Last a) Source 
ToSchema a => ToSchema (IntMap a) Source

NOTE: This schema does not account for the uniqueness of keys.

ToSchema a => ToSchema (Set a) Source 
ToSchema a => ToSchema (Vector a) Source 
ToSchema a => ToSchema (Vector a) Source 
ToSchema a => ToSchema (Vector a) Source 
ToSchema a => ToSchema (Vector a) Source 
ToSchema a => ToSchema (HashSet a) Source 
(ToSchema a, ToSchema b) => ToSchema (Either a b) Source 
(ToSchema a, ToSchema b) => ToSchema (a, b) Source 
ToSchema a => ToSchema (HashMap String a) Source 
ToSchema a => ToSchema (HashMap Text a) Source 
ToSchema a => ToSchema (HashMap Text a) Source 
ToSchema a => ToSchema (Map String a) Source 
ToSchema a => ToSchema (Map Text a) Source 
ToSchema a => ToSchema (Map Text a) Source 
(ToSchema a, ToSchema b, ToSchema c) => ToSchema (a, b, c) Source 
(ToSchema a, ToSchema b, ToSchema c, ToSchema d) => ToSchema (a, b, c, d) Source 
(ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e) => ToSchema (a, b, c, d, e) Source 
(ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f) => ToSchema (a, b, c, d, e, f) Source 
(ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f, ToSchema g) => ToSchema (a, b, c, d, e, f, g) Source 

declareSchema :: ToSchema a => proxy a -> Declare (Definitions Schema) Schema Source

Convert a type into a schema and declare all used schema definitions.

declareSchemaRef :: ToSchema a => proxy a -> Declare (Definitions Schema) (Referenced Schema) Source

Convert a type into a referenced schema if possible and declare all used schema definitions. Only named schemas can be referenced, nameless schemas are inlined.

Schema definitions are typically declared for every referenced schema. If declareSchemaRef returns a reference, a corresponding schema will be declared (regardless of whether it is recusive or not).

toSchema :: ToSchema a => proxy a -> Schema Source

Convert a type into a schema.

>>> encode $ toSchema (Proxy :: Proxy Int8)
"{\"maximum\":127,\"minimum\":-128,\"type\":\"integer\"}"
>>> encode $ toSchema (Proxy :: Proxy [Day])
"{\"items\":{\"$ref\":\"#/definitions/Day\"},\"type\":\"array\"}"

toSchemaRef :: ToSchema a => proxy a -> Referenced Schema Source

Convert a type into a referenced schema if possible. Only named schemas can be referenced, nameless schemas are inlined.

>>> encode $ toSchemaRef (Proxy :: Proxy Integer)
"{\"type\":\"integer\"}"
>>> encode $ toSchemaRef (Proxy :: Proxy Day)
"{\"$ref\":\"#/definitions/Day\"}"

schemaName :: ToSchema a => proxy a -> Maybe Text Source

Get type's schema name according to its ToSchema instance.

>>> schemaName (Proxy :: Proxy Int)
Nothing
>>> schemaName (Proxy :: Proxy UTCTime)
Just "UTCTime"

toInlinedSchema :: ToSchema a => proxy a -> Schema Source

Convert a type into a schema without references.

>>> encode $ toInlinedSchema (Proxy :: Proxy [Day])
"{\"items\":{\"format\":\"date\",\"type\":\"string\"},\"type\":\"array\"}"

WARNING: toInlinedSchema will produce infinite schema when inlining recursive schemas.

Generic schema encoding

genericDeclareNamedSchema :: forall a proxy. (Generic a, GToSchema (Rep a)) => SchemaOptions -> proxy a -> Declare (Definitions Schema) NamedSchema Source

A configurable generic NamedSchema creator. This function applied to defaultSchemaOptions is used as the default for declareNamedSchema when the type is an instance of Generic.

genericDeclareSchema :: (Generic a, GToSchema (Rep a)) => SchemaOptions -> proxy a -> Declare (Definitions Schema) Schema Source

A configurable generic Schema creator.

genericToNamedSchemaBoundedIntegral :: forall a d f proxy. (Bounded a, Integral a, Generic a, Rep a ~ D1 d f, Datatype d) => SchemaOptions -> proxy a -> NamedSchema Source

Default generic named schema for Bounded, Integral types.

toSchemaBoundedIntegral :: forall a proxy. (Bounded a, Integral a) => proxy a -> Schema Source

Default schema for Bounded, Integral types.

>>> encode $ toSchemaBoundedIntegral (Proxy :: Proxy Int16)
"{\"maximum\":32767,\"minimum\":-32768,\"type\":\"integer\"}"

paramSchemaToNamedSchema :: forall a d f proxy. (ToParamSchema a, Generic a, Rep a ~ D1 d f, Datatype d) => SchemaOptions -> proxy a -> NamedSchema Source

Lift a plain ParamSchema into a model NamedSchema.

paramSchemaToSchema :: forall a proxy. ToParamSchema a => proxy a -> Schema Source

Lift a plain ParamSchema into a model Schema.

Schema templates

passwordSchema :: Schema Source

Default schema for password string. "password" format is used to hint UIs the input needs to be obscured.

binarySchema :: Schema Source

Default schema for binary data (any sequence of octets).

byteSchema :: Schema Source

Default schema for binary data (base64 encoded).

Sketching Schemas using ToJSON

sketchSchema :: ToJSON a => a -> Schema Source

Make an unrestrictive sketch of a Schema based on a ToJSON instance. Produced schema can be used for further refinement.

>>> encode $ sketchSchema "hello"
"{\"example\":\"hello\",\"type\":\"string\"}"
>>> encode $ sketchSchema (1, 2, 3)
"{\"example\":[1,2,3],\"items\":{\"type\":\"number\"},\"type\":\"array\"}"
>>> encode $ sketchSchema ("Jack", 25)
"{\"example\":[\"Jack\",25],\"items\":[{\"type\":\"string\"},{\"type\":\"number\"}],\"type\":\"array\"}"
>>> data Person = Person { name :: String, age :: Int } deriving (Generic)
>>> instance ToJSON Person
>>> encode $ sketchSchema (Person "Jack" 25)
"{\"example\":{\"age\":25,\"name\":\"Jack\"},\"required\":[\"age\",\"name\"],\"type\":\"object\",\"properties\":{\"age\":{\"type\":\"number\"},\"name\":{\"type\":\"string\"}}}"

sketchStrictSchema :: ToJSON a => a -> Schema Source

Make a restrictive sketch of a Schema based on a ToJSON instance. Produced schema uses as much constraints as possible.

>>> encode $ sketchStrictSchema "hello"
"{\"maxLength\":5,\"pattern\":\"hello\",\"minLength\":5,\"type\":\"string\",\"enum\":[\"hello\"]}"
>>> encode $ sketchStrictSchema (1, 2, 3)
"{\"minItems\":3,\"uniqueItems\":true,\"items\":[{\"maximum\":1,\"minimum\":1,\"multipleOf\":1,\"type\":\"number\",\"enum\":[1]},{\"maximum\":2,\"minimum\":2,\"multipleOf\":2,\"type\":\"number\",\"enum\":[2]},{\"maximum\":3,\"minimum\":3,\"multipleOf\":3,\"type\":\"number\",\"enum\":[3]}],\"maxItems\":3,\"type\":\"array\",\"enum\":[[1,2,3]]}"
>>> encode $ sketchStrictSchema ("Jack", 25)
"{\"minItems\":2,\"uniqueItems\":true,\"items\":[{\"maxLength\":4,\"pattern\":\"Jack\",\"minLength\":4,\"type\":\"string\",\"enum\":[\"Jack\"]},{\"maximum\":25,\"minimum\":25,\"multipleOf\":25,\"type\":\"number\",\"enum\":[25]}],\"maxItems\":2,\"type\":\"array\",\"enum\":[[\"Jack\",25]]}"
>>> data Person = Person { name :: String, age :: Int } deriving (Generic)
>>> instance ToJSON Person
>>> encode $ sketchStrictSchema (Person "Jack" 25)
"{\"minProperties\":2,\"required\":[\"age\",\"name\"],\"maxProperties\":2,\"type\":\"object\",\"enum\":[{\"age\":25,\"name\":\"Jack\"}],\"properties\":{\"age\":{\"maximum\":25,\"minimum\":25,\"multipleOf\":25,\"type\":\"number\",\"enum\":[25]},\"name\":{\"maxLength\":4,\"pattern\":\"Jack\",\"minLength\":4,\"type\":\"string\",\"enum\":[\"Jack\"]}}}"

Inlining Schemas

inlineNonRecursiveSchemas :: Data s => Definitions Schema -> s -> s Source

Inline all non-recursive schemas for which the definition can be found in Definitions.

inlineAllSchemas :: Data s => Definitions Schema -> s -> s Source

Inline all schema references for which the definition can be found in Definitions.

WARNING: inlineAllSchemas will produce infinite schemas when inlining recursive schemas.

inlineSchemas :: Data s => [Text] -> Definitions Schema -> s -> s Source

Inline any referenced schema if its name is in the given list.

NOTE: if a referenced schema is not found in definitions it stays referenced even if it appears in the list of names.

WARNING: inlineSchemas will produce infinite schemas when inlining recursive schemas.

inlineSchemasWhen :: Data s => (Text -> Bool) -> Definitions Schema -> s -> s Source

Inline any referenced schema if its name satisfies given predicate.

NOTE: if a referenced schema is not found in definitions the predicate is ignored and schema stays referenced.

WARNING: inlineSchemasWhen will produce infinite schemas when inlining recursive schemas.

Generic encoding configuration

data SchemaOptions Source

Options that specify how to encode your type to Swagger schema.

Constructors

SchemaOptions 

Fields

fieldLabelModifier :: String -> String

Function applied to field labels. Handy for removing common record prefixes for example.

constructorTagModifier :: String -> String

Function applied to constructor tags which could be handy for lower-casing them for example.

datatypeNameModifier :: String -> String

Function applied to datatype name.

allNullaryToStringTag :: Bool

If True the constructors of a datatype, with all nullary constructors, will be encoded to a string enumeration schema with the constructor tags as possible values.

unwrapUnaryRecords :: Bool

Hide the field name when a record constructor has only one field, like a newtype.