A Self-documenting encoder and decoder,
also called an Autodocodec.
In an ideal situation, this type would have only one type parameter: 'Codec value'. This does not work very well because we want to be able to implement Functor and Applicative, which each require a kind '* -> *'. So instead we use two type parameters.
The two type parameters correspond to the phase in which they are used:
The
inputparameter is used for the type that is used during encoding of a value, so it's theinputto the codec.The
outputparameter is used for the type that is used during decoding of a value, so it's theoutputof the codec.Both parameters are unused during documentation.
Constructors
NullCodec :: (Coercible input (), Coercible output ()) => Codec Value input outputEncode
()to thenullvalue, and decodenullas().BoolCodec :: (Coercible input Bool, Coercible output Bool) => Maybe Text -> Codec Value input outputStringCodec :: (Coercible input Text, Coercible output Text) => Maybe Text -> Codec Value input outputIntegerCodec :: (Coercible input Integer, Coercible output Integer) => Maybe Text -> Bounds Integer -> Codec Value input outputEncode Integer to a
numbervalue, and decode anumbervalue as an Integer.The number has 'Bounds Integer'. These are only enforced at decoding time, not at encoding-time.
NOTE: Decoding Integers is dangerous so decoding may fail for enormous numbers. API NOTE: This is separate from NumberCodec so that we can produce more precise documentation about whether the numbers are integers.
NumberCodec :: (Coercible input Scientific, Coercible output Scientific) => Maybe Text -> Bounds Scientific -> Codec Value input outputEncode Scientific to a
numbervalue, and decode anumbervalue as a Scientific.The number has 'Bounds Scientific'. These are only enforced at decoding time, not at encoding-time.
NOTE: We use Scientific here because that is what aeson uses.
HashMapCodec :: (Eq k, Hashable k, FromJSONKey k, ToJSONKey k, Coercible input (HashMap k v), Coercible output (HashMap k v)) => JSONCodec v -> Codec Value input outputMapCodec :: (Ord k, FromJSONKey k, ToJSONKey k, Coercible input (Map k v), Coercible output (Map k v)) => JSONCodec v -> Codec Value input outputValueCodec :: (Coercible Value input, Coercible Value output) => Codec Value input outputArrayOfCodec :: (Coercible input (Vector input1), Coercible output (Vector output1)) => Maybe Text -> ValueCodec input1 output1 -> Codec Value input outputObjectOfCodec :: Maybe Text -> ObjectCodec input output -> Codec Value input outputEncode a value as a an
objectvalue using the given ObjectCodec, and decode anobjectvalue as a value using the given ObjectCodec.EqCodec :: (Show value, Eq value, Coercible input value, Coercible output value) => value -> JSONCodec value -> Codec Value input outputMatch a given value using its Eq instance during decoding, and encode exactly that value during encoding.
BimapCodec :: (oldOutput -> Either String output) -> (input -> oldInput) -> Codec context oldInput oldOutput -> Codec context input outputMap a codec in both directions.
This is not strictly dimap, because the decoding function is allowed to fail, but we can implement dimap using this function by using a decoding function that does not fail. Otherwise we would have to have another constructor here.
EitherCodec :: (Coercible input (Either input1 input2), Coercible output (Either output1 output2)) => !Union -> Codec context input1 output1 -> Codec context input2 output2 -> Codec context input outputEncode/Decode an Either value
During encoding, encode either value of an Either using their own codec. During decoding, try to parse the Left side first, and the Right side only when that fails.
This codec is used to implement choice.
Note that this codec works for both values and objects. However: due to the complex nature of documentation, the documentation may not be as good as you would hope when you use this codec. In particular, you should prefer using it for values rather than objects, because those docs are easier to generate.
DiscriminatedUnionCodec :: Text -> (input -> (Discriminator, ObjectCodec input ())) -> HashMap Discriminator (Text, ObjectCodec Void output) -> Codec (KeyMap Value) input outputEncode/decode a discriminated union of objects
The type of object being encoded/decoded is discriminated by a designated "discriminator" property on the object which takes a string value.
When encoding, the provided function is applied to the input to obtain a new encoder for the input. The function mapToEncoder is provided to assist with building these encoders.
When decoding, the value of the discriminator property is looked up in the HashMap to obtain a decoder for the output. The function
mapToDecoderis provided to assist with building these decoders. See examples inUsage.hs.The HashMap is also used to generate schemas for the type. In particular, for OpenAPI 3, it will generate a schema with a
discriminator, as defined by https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/CommentCodec :: Text -> ValueCodec input output -> Codec Value input outputA comment codec
This is used to add implementation-irrelevant but human-relevant information.
ReferenceCodec :: Text -> ~ValueCodec input output -> Codec Value input outputA reference codec
This is used for naming a codec, so that recursive codecs can have a finite schema.
It doesn't _need_ to be recursive, and you may just have wanted to name the codec, but it _may_ be recursive from here downward.
This value MUST be lazy, otherwise we can never define recursive codecs.
RequiredKeyCodec :: (Coercible input input1, Coercible output output1) => Text -> ValueCodec input1 output1 -> Maybe Text -> Codec (KeyMap Value) input outputOptionalKeyCodec :: (Coercible input (Maybe input1), Coercible output (Maybe output1)) => Text -> ValueCodec input1 output1 -> Maybe Text -> Codec (KeyMap Value) input outputOptionalKeyWithDefaultCodec :: Coercible output input => Text -> ValueCodec input input -> input -> Maybe Text -> Codec (KeyMap Value) input outputOptionalKeyWithOmittedDefaultCodec :: (Eq value, Coercible input value, Coercible output value) => Text -> ValueCodec value value -> value -> Maybe Text -> Codec (KeyMap Value) input outputPureCodec :: output -> Codec (KeyMap Value) input outputTo implement pure from Applicative.
Pure is not available for non-object codecs because there is no mempty for Value, which we would need during encoding.
ApCodec :: ObjectCodec input (output1 -> output) -> ObjectCodec input output1 -> Codec (KeyMap Value) input outputTo implement <*> from Applicative.
Ap is not available for non-object codecs because we cannot combine (mappend) two encoded Values
Instances2Applicative, Functor
Applicative (ObjectCodec input)Defined in autodocodec-0.5.0.0 · Autodocodec.CodecFunctor (Codec context input)Defined in autodocodec-0.5.0.0 · Autodocodec.Codec