Safe Haskell | None |
---|---|
Language | GHC2021 |
Data.Schema
Description
Combinator library for defining bidirectional JSON encodings with associated Swagger schemas.
Documentation on the organisation of this library and a tutorial
can be found in README.md
.
Synopsis
- data SchemaP doc v w a b
- type ValueSchema doc a = ValueSchemaP doc a a
- type ValueSchemaP doc = SchemaP doc Value Value
- type ObjectSchema doc a = ObjectSchemaP doc a a
- type ObjectSchemaP doc = SchemaP doc Object [Pair]
- class ToSchema a where
- newtype Schema a = Schema {
- getSchema :: a
- mkSchema :: doc -> (v -> Parser b) -> (a -> Maybe w) -> SchemaP doc v w a b
- schemaDoc :: SchemaP ss v m a b -> ss
- schemaIn :: SchemaP doc v v' a b -> v -> Parser b
- schemaOut :: SchemaP ss v m a b -> a -> Maybe m
- class HasDoc a a' doc doc' | a a' -> doc doc' where
- class HasOpt doc where
- mkOpt :: doc -> doc
- doc' :: forall doc v w a b f. Functor f => (doc -> f doc) -> SchemaP doc v w a b -> f (SchemaP doc v w a b)
- class HasSchemaRef doc where
- schemaRef :: doc -> WithDeclare (Referenced Schema)
- class Monoid doc => HasObject doc ndoc | doc -> ndoc, ndoc -> doc where
- mkObject :: Text -> doc -> ndoc
- unmkObject :: ndoc -> doc
- class Monoid doc => HasField ndoc doc | ndoc -> doc where
- withParser :: SchemaP doc v w a b -> (b -> Parser b') -> SchemaP doc v w a b'
- type SwaggerDoc = WithDeclare Schema
- swaggerDoc :: ToSchema a => NamedSwaggerDoc
- type NamedSwaggerDoc = WithDeclare NamedSchema
- data WithDeclare s
- declareSwaggerSchema :: SchemaP (WithDeclare d) v w a b -> Declare d
- getName :: HasName doc => doc -> Maybe Text
- object :: HasObject doc doc' => Text -> SchemaP doc Object [Pair] a b -> SchemaP doc' Value Value a b
- objectWithDocModifier :: HasObject doc doc' => Text -> (doc' -> doc') -> ObjectSchema doc a -> ValueSchema doc' a
- objectOver :: HasObject doc doc' => Lens v v' Value Object -> Text -> SchemaP doc v' [Pair] a b -> SchemaP doc' v Value a b
- jsonObject :: ValueSchema SwaggerDoc Object
- jsonValue :: ValueSchema SwaggerDoc Value
- field :: HasField doc' doc => Text -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b
- fieldWithDocModifier :: HasField doc' doc => Text -> (doc' -> doc') -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b
- optField :: (HasOpt doc, HasField doc' doc) => Text -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a (Maybe b)
- optField' :: (HasOpt doc, HasField doc' doc) => Text -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a (Maybe b)
- optFieldWithDocModifier :: (HasOpt doc, HasField doc' doc) => Text -> (doc' -> doc') -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a (Maybe b)
- fieldOver :: HasField doc' doc => Lens v v' Object Value -> Text -> SchemaP doc' v' Value a b -> SchemaP doc v [Pair] a b
- array :: (HasArray ndoc doc, HasName ndoc) => ValueSchema ndoc a -> ValueSchema doc [a]
- set :: (HasArray ndoc doc, HasName ndoc, Ord a) => ValueSchema ndoc a -> ValueSchema doc (Set a)
- vector :: (HasArray ndoc doc, HasName ndoc) => ValueSchema ndoc a -> ValueSchema doc (Vector a)
- nonEmptyArray :: (HasArray ndoc doc, HasName ndoc, HasMinItems doc (Maybe Integer)) => ValueSchema ndoc a -> ValueSchema doc (NonEmpty a)
- map_ :: (HasMap ndoc doc, Ord k, FromJSONKey k, ToJSONKey k) => ValueSchema ndoc a -> ValueSchema doc (Map k a)
- mapWithKeys :: (HasMap ndoc doc, Ord k) => (k -> Text) -> (Text -> k) -> ValueSchema ndoc a -> ValueSchema doc (Map k a)
- enum :: (With v, HasEnum v doc) => Text -> SchemaP [Value] v (Alt Maybe v) a b -> SchemaP doc Value Value a b
- maybe_ :: Monoid w => SchemaP d v w a b -> SchemaP d v w (Maybe a) b
- maybeWithDefault :: w -> SchemaP d v w a b -> SchemaP d v w (Maybe a) b
- bind :: (Monoid d, Monoid w) => SchemaP d v w a b -> SchemaP d (v, b) w a c -> SchemaP d v w a (b, c)
- dispatch :: (Bounded t, Enum t, Monoid d) => (t -> SchemaP d v w a b) -> SchemaP d (v, t) w a b
- text :: Text -> ValueSchema NamedSwaggerDoc Text
- parsedText :: Text -> (Text -> Either String a) -> SchemaP NamedSwaggerDoc Value Value Text a
- parsedTextWithDoc :: Text -> Text -> (Text -> Either String a) -> SchemaP NamedSwaggerDoc Value Value Text a
- null_ :: Monoid d => ValueSchemaP d () ()
- nullable :: Monoid d => ValueSchema d a -> ValueSchema d (Maybe a)
- element :: (ToJSON a, Eq a, Eq b) => a -> b -> SchemaP [Value] a (Alt Maybe a) b b
- tag :: Prism b b' a a' -> SchemaP ss v m a a' -> SchemaP ss v m b b'
- unnamed :: HasObject doc doc' => SchemaP doc' v m a b -> SchemaP doc v m a b
- named :: HasObject doc doc' => Text -> SchemaP doc v m a b -> SchemaP doc' v m a b
- (.=) :: Profunctor p => (a -> a') -> p a' b -> p a b
- schemaToSwagger :: ToSchema a => Proxy a -> Declare NamedSchema
- schemaToJSON :: ToSchema a => a -> Value
- schemaParseJSON :: ToSchema a => Value -> Parser a
- genericToSchema :: (ToSchema a, ToJSON a, FromJSON a) => ValueSchema NamedSwaggerDoc a
- description :: HasDescription s a => Lens' s a
Documentation
data SchemaP doc v w a b Source #
A combined JSON encoder-decoder with associated documentation.
A value of type 'SchemaP d v w a b', which we will refer to as a schema, contains both a JSON parser and a JSON serialiser, together with documentation-like metadata, such as a JSON or Swagger schema.
The type variables are as follows:
d
- documentation type, usually a
Monoid
. v
- type of JSON values being parsed (e.g.
Value
). w
- type of JSON values being serialised (e.g.
Value
). a
- input type
b
- output type
Input and output types deserve some more explanation. We can think
of a value sch
of type 'SchemaP d v w a b' as a kind of special
"function" from a
to b
, but where a
and b
might potentially
live in different "languages". The parser portion of sch
takes a
JSON-encoded value of type a
and produces a value of type b
,
while the serialiser portion of sch
takes a haskell value of type
a
and produces a JSON-encoding of something of type b
.
In terms of composability, this way of representing schemas (based on input and output types) is superior to the perhaps more natural approach of using "bidirectional functions" or isomorphisms (based on a single type parameter).
Although schemas cannot be composed as functions (i.e. they do not
form a Category
), they still admit a number of important and
useful instances, such as Profunctor
(and specifically Choice
),
which makes it possible to use prism quite effectively to build
schema values.
Using type variables to represent JSON types might seem like
excessive generality, but it is useful to represent "intermediate"
schemas arising when building complex ones. For example, a schema
which is able to work with fields of a JSON object (see field
)
should not output full-blown objects, but only lists of pairs, so
that they can be combined correctly via the usual Monoid
structure of lists when using the Applicative
interface of
'SchemaP d v w a b'.
The idea of using the profunctor structure of SchemaP
is taken
from the codec library.
Instances
Choice (SchemaP doc v v') Source # | |
Profunctor (SchemaP doc v v') Source # | |
Defined in Data.Schema Methods dimap :: (a -> b) -> (c -> d) -> SchemaP doc v v' b c -> SchemaP doc v v' a d Source # lmap :: (a -> b) -> SchemaP doc v v' b c -> SchemaP doc v v' a c Source # rmap :: (b -> c) -> SchemaP doc v v' a b -> SchemaP doc v v' a c Source # (#.) :: forall a b c q. Coercible c b => q b c -> SchemaP doc v v' a b -> SchemaP doc v v' a c Source # (.#) :: forall a b c q. Coercible b a => SchemaP doc v v' b c -> q a b -> SchemaP doc v v' a c Source # | |
(NearSemiRing doc, Monoid v') => Alternative (SchemaP doc v v' a) Source # | |
(Monoid doc, Monoid v') => Applicative (SchemaP doc v v' a) Source # | |
Defined in Data.Schema Methods pure :: a0 -> SchemaP doc v v' a a0 # (<*>) :: SchemaP doc v v' a (a0 -> b) -> SchemaP doc v v' a a0 -> SchemaP doc v v' a b # liftA2 :: (a0 -> b -> c) -> SchemaP doc v v' a a0 -> SchemaP doc v v' a b -> SchemaP doc v v' a c # (*>) :: SchemaP doc v v' a a0 -> SchemaP doc v v' a b -> SchemaP doc v v' a b # (<*) :: SchemaP doc v v' a a0 -> SchemaP doc v v' a b -> SchemaP doc v v' a a0 # | |
Functor (SchemaP doc v w a) Source # | |
Monoid doc => Monoid (SchemaP doc v v' a b) Source # | |
Semigroup doc => Semigroup (SchemaP doc v v' a b) Source # | |
HasSchema d Schema => HasSchema (SchemaP d v w a b) Schema Source # | |
HasDoc (SchemaP doc v v' a b) (SchemaP doc' v v' a b) doc doc' Source # | |
type ValueSchema doc a = ValueSchemaP doc a a Source #
type ObjectSchema doc a = ObjectSchemaP doc a a Source #
class ToSchema a where Source #
A type with a canonical typed schema definition.
Using ToSchema, one can split a complicated shema definition
into manageable parts by defining instances for the various types
involved, and using the schema
method to reuse the
previously-defined schema definitions for component types.
Methods
Instances
ToSchema Int32 Source # | |
Defined in Data.Schema Methods | |
ToSchema Int64 Source # | |
Defined in Data.Schema Methods | |
ToSchema Word16 Source # | |
Defined in Data.Schema Methods | |
ToSchema Word32 Source # | |
Defined in Data.Schema Methods | |
ToSchema Word64 Source # | |
Defined in Data.Schema Methods | |
ToSchema Word8 Source # | |
Defined in Data.Schema Methods | |
ToSchema Text Source # | |
Defined in Data.Schema Methods | |
ToSchema Text Source # | |
Defined in Data.Schema Methods | |
ToSchema String Source # | |
Defined in Data.Schema Methods | |
ToSchema Integer Source # | |
Defined in Data.Schema Methods | |
ToSchema Natural Source # | |
Defined in Data.Schema Methods | |
ToSchema Bool Source # | |
Defined in Data.Schema Methods | |
ToSchema Char Source # | |
Defined in Data.Schema Methods | |
ToSchema Int Source # | |
Defined in Data.Schema Methods | |
ToSchema Word Source # | |
Defined in Data.Schema Methods |
Instances
ToSchema a => FromJSON (Schema a) Source # | |||||
ToSchema a => ToJSON (Schema a) Source # | |||||
Generic (Schema a) Source # | |||||
Defined in Data.Schema Associated Types
| |||||
(Typeable a, ToSchema a) => ToSchema (Schema a) Source # | |||||
Defined in Data.Schema Methods declareNamedSchema :: Proxy (Schema a) -> Declare (Definitions Schema) NamedSchema Source # | |||||
type Rep (Schema a) Source # | |||||
Defined in Data.Schema |
mkSchema :: doc -> (v -> Parser b) -> (a -> Maybe w) -> SchemaP doc v w a b Source #
Build a schema from documentation, parser and serialiser
class HasOpt doc where Source #
Instances
HasOpt NamedSwaggerDoc Source # | |
Defined in Data.Schema Methods | |
HasOpt SwaggerDoc Source # | |
Defined in Data.Schema Methods mkOpt :: SwaggerDoc -> SwaggerDoc Source # |
doc' :: forall doc v w a b f. Functor f => (doc -> f doc) -> SchemaP doc v w a b -> f (SchemaP doc v w a b) Source #
class HasSchemaRef doc where Source #
Methods
schemaRef :: doc -> WithDeclare (Referenced Schema) Source #
Instances
HasSchemaRef NamedSwaggerDoc Source # | |
Defined in Data.Schema Methods schemaRef :: NamedSwaggerDoc -> WithDeclare (Referenced Schema) Source # | |
HasSchemaRef SwaggerDoc Source # | |
Defined in Data.Schema Methods schemaRef :: SwaggerDoc -> WithDeclare (Referenced Schema) Source # |
class Monoid doc => HasObject doc ndoc | doc -> ndoc, ndoc -> doc where Source #
Instances
HasObject SwaggerDoc NamedSwaggerDoc Source # | |
Defined in Data.Schema Methods mkObject :: Text -> SwaggerDoc -> NamedSwaggerDoc Source # |
class Monoid doc => HasField ndoc doc | ndoc -> doc where Source #
Instances
HasSchemaRef doc => HasField doc SwaggerDoc Source # | |
Defined in Data.Schema Methods mkField :: Text -> doc -> SwaggerDoc Source # |
type SwaggerDoc = WithDeclare Schema Source #
swaggerDoc :: ToSchema a => NamedSwaggerDoc Source #
type NamedSwaggerDoc = WithDeclare NamedSchema Source #
data WithDeclare s Source #
Instances
declareSwaggerSchema :: SchemaP (WithDeclare d) v w a b -> Declare d Source #
object :: HasObject doc doc' => Text -> SchemaP doc Object [Pair] a b -> SchemaP doc' Value Value a b Source #
A schema for a JSON object.
This can be used to convert a combination of schemas obtained using
field
into a single schema for a JSON object.
objectWithDocModifier :: HasObject doc doc' => Text -> (doc' -> doc') -> ObjectSchema doc a -> ValueSchema doc' a Source #
Like object
, but apply an arbitrary function to the
documentation of the resulting object.
objectOver :: HasObject doc doc' => Lens v v' Value Object -> Text -> SchemaP doc v' [Pair] a b -> SchemaP doc' v Value a b Source #
jsonObject :: ValueSchema SwaggerDoc Object Source #
A schema for an arbitrary JSON object.
jsonValue :: ValueSchema SwaggerDoc Value Source #
A schema for an arbitrary JSON value.
field :: HasField doc' doc => Text -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b Source #
A schema for a one-field JSON object.
fieldWithDocModifier :: HasField doc' doc => Text -> (doc' -> doc') -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b Source #
Like field
, but apply an arbitrary function to the
documentation of the field.
optField :: (HasOpt doc, HasField doc' doc) => Text -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a (Maybe b) Source #
A schema for a JSON object with a single optional field.
optField' :: (HasOpt doc, HasField doc' doc) => Text -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a (Maybe b) Source #
optFieldWithDocModifier :: (HasOpt doc, HasField doc' doc) => Text -> (doc' -> doc') -> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a (Maybe b) Source #
Like optField
, but apply an arbitrary function to the
documentation of the field.
fieldOver :: HasField doc' doc => Lens v v' Object Value -> Text -> SchemaP doc' v' Value a b -> SchemaP doc v [Pair] a b Source #
Like fieldOverF
, but specialised to the identity functor.
array :: (HasArray ndoc doc, HasName ndoc) => ValueSchema ndoc a -> ValueSchema doc [a] Source #
A schema for a JSON array.
set :: (HasArray ndoc doc, HasName ndoc, Ord a) => ValueSchema ndoc a -> ValueSchema doc (Set a) Source #
vector :: (HasArray ndoc doc, HasName ndoc) => ValueSchema ndoc a -> ValueSchema doc (Vector a) Source #
nonEmptyArray :: (HasArray ndoc doc, HasName ndoc, HasMinItems doc (Maybe Integer)) => ValueSchema ndoc a -> ValueSchema doc (NonEmpty a) Source #
map_ :: (HasMap ndoc doc, Ord k, FromJSONKey k, ToJSONKey k) => ValueSchema ndoc a -> ValueSchema doc (Map k a) Source #
A schema for a JSON object with arbitrary keys of type k
. The type of
keys must have instances for FromJSONKey
and ToJSONKey
.
Use mapWithKeys
for key types that do not have such instances.
mapWithKeys :: (HasMap ndoc doc, Ord k) => (k -> Text) -> (Text -> k) -> ValueSchema ndoc a -> ValueSchema doc (Map k a) Source #
A schema for a JSON object with arbitrary keys of type k
, where k
can
be converted to and from Text
.
enum :: (With v, HasEnum v doc) => Text -> SchemaP [Value] v (Alt Maybe v) a b -> SchemaP doc Value Value a b Source #
A schema for a JSON enumeration.
This is used to convert a combination of schemas obtained using
element
into a single schema for a JSON string.
maybe_ :: Monoid w => SchemaP d v w a b -> SchemaP d v w (Maybe a) b Source #
A schema for Maybe
that omits a field on serialisation.
This is most commonly used for optional fields, and it will cause the field to be omitted from the output of the serialiser.
maybeWithDefault :: w -> SchemaP d v w a b -> SchemaP d v w (Maybe a) b Source #
A schema for Maybe
, producing the given default value on serialisation.
bind :: (Monoid d, Monoid w) => SchemaP d v w a b -> SchemaP d (v, b) w a c -> SchemaP d v w a (b, c) Source #
A schema depending on a parsed value.
Even though SchemaP
does not expose a monadic interface, it is possible to
make the parser of a schema depend on the values parsed by a previous
schema.
For example, a schema for an object containing a "type" field which
determines how the rest of the object is parsed. To construct the schema to
use as the second argument of bind
, one can use dispatch
.
dispatch :: (Bounded t, Enum t, Monoid d) => (t -> SchemaP d v w a b) -> SchemaP d (v, t) w a b Source #
A union of schemas over a finite type of "tags".
Normally used together with bind
to construct schemas that depend on some
"tag" value.
text :: Text -> ValueSchema NamedSwaggerDoc Text Source #
A schema for a textual value.
parsedText :: Text -> (Text -> Either String a) -> SchemaP NamedSwaggerDoc Value Value Text a Source #
A schema for a textual value with possible failure.
parsedTextWithDoc :: Text -> Text -> (Text -> Either String a) -> SchemaP NamedSwaggerDoc Value Value Text a Source #
A schema for a textual value with possible failure.
null_ :: Monoid d => ValueSchemaP d () () Source #
A schema for a null value.
nullable :: Monoid d => ValueSchema d a -> ValueSchema d (Maybe a) Source #
A schema for a nullable value.
The parser accepts a JSON null as a valid value, and converts it to
Nothing
. Any non-null value is parsed using the underlying schema.
The serialiser behaves similarly, but in the other direction.
element :: (ToJSON a, Eq a, Eq b) => a -> b -> SchemaP [Value] a (Alt Maybe a) b b Source #
A schema for a single value of an enumeration.
tag :: Prism b b' a a' -> SchemaP ss v m a a' -> SchemaP ss v m b b' Source #
Change the input and output types of a schema via a prism.
unnamed :: HasObject doc doc' => SchemaP doc' v m a b -> SchemaP doc v m a b Source #
Turn a named schema into an unnamed one.
This is mostly useful when using a schema as a field of a bigger schema. If the inner schema is unnamed, it gets "inlined" in the larger scheme definition, and otherwise it gets "referenced". This combinator makes it possible to choose one of the two options.
named :: HasObject doc doc' => Text -> SchemaP doc v m a b -> SchemaP doc' v m a b Source #
Attach a name to a schema.
This only affects the documentation portion of a schema, and not the parsing or serialisation.
(.=) :: Profunctor p => (a -> a') -> p a' b -> p a b Source #
Change the input type of a schema.
schemaToSwagger :: ToSchema a => Proxy a -> Declare NamedSchema Source #
genericToSchema :: (ToSchema a, ToJSON a, FromJSON a) => ValueSchema NamedSwaggerDoc a Source #
description :: HasDescription s a => Lens' s a Source #