A codec specifies how to map from and to raw values that are sent over the network. Raw values, which are natively
supported by client/server interpreters, include
Strings, byte arrays,
Files and multiparts.
There are built-in codecs for most common types such as
Int etc. Codecs are usually defined as implicit
values and resolved implicitly when they are referenced.
For example, a
query[Int]("quantity") specifies an input parameter which corresponds to the
parameter and will be mapped as an
Int. There’s an implicit
Codec[Int] value that is referenced by the
method (which is defined in the
In a server setting, if the value cannot be parsed as an int, a decoding failure is reported, and the endpoint
won’t match the request, or a
400 Bad Request response is returned (depending on configuration).
Optional and multiple parameters¶
Some inputs/outputs allow optional, or multiple parameters:
- path segments are always required
- query and header values can be optional or multiple (repeated query parameters/headers)
- bodies can be optional, but not multiple
In general, optional parameters are represented as
Option values, and multiple parameters as
header[Option[String]]("X-Auth-Token") describes an optional header. An input described as
query[List[String]]("color") allows multiple occurences of the
color query parameter, with all values gathered
into a list.
Note that only textual bodies can be optional (optional binary/streaming bodies aren’t supported). That’s because a body
cannot be missing - there’s always some body. This is unlike e.g. a query parameter: for which a value can be present,
a value can be empty (but defined!), or the parameter might be missing altogether - which corresponds to a
That’s why only strict (non-streaming) textual bodies, which are empty (
""), will be considered as an empty value
None), if the codec allows optional values.
To support optional and multiple parameters, inputs/outputs don’t require implicit
Codec values (which represent
only mandatory values), but
CodecForMany implicit values.
CodecForOptional can be used in a context which allows optional values. Given a
Codec[T], instances of both
CodecForOptional[Option[T]] will be generated (that’s also the way to add support for
custom optional types). The first one will require a value, and report a decoding failure if a value is missing. The
second will properly map to an
Option, depending if the value is present or not.
A codec also contains the schema of the mapped type. This schema information is used when generating documentation.
Schemas consists of the schema type, which is one of the values defined in
SchemaType, such as
SProduct (for objects). Moreover, a schema contains meta-data: value optionality,
description and low-level format.
For primitive types, the schema values are built-in, and defined in the
Schema companion object.
The schema is left unchanged when mapping over a codec, as the underlying representation of the value doesn’t change.
When codecs are derived for complex types, e.g. for json mapping, schemas are looked up through implicit
Schema[T] values. See custom types for more details.
Codecs carry an additional type parameter, which specifies the codec format. Each format corresponds to a media type,
which describes the low-level format of the raw value (to which the codec encodes). Some built-in formats include
multipart/form-data. Custom formats can be added by creating an
implementation of the
Thanks to codec being parametrised by codec formats, it is possible to have a
Codec[MyCaseClass, TextPlain, _] which
specifies how to serialize a case class to plain text, and a different
Codec[MyCaseClass, Json, _], which specifies
how to serialize a case class to json. Both can be implicitly available without implicit resolution conflicts.
Different codec formats can be used in different contexts. When defining a path, query or header parameter, only a codec
TextPlain media type can be used. However, for bodies, any media types is allowed. For example, the
input/output described by
jsonBody[T] requires a json codec.