Datatypes integrations
Note
Note that the codecs defined by the tapir integrations are used only when the specific types (e.g. enumerations0 are used at the top level. Any nested usages (e.g. as part of a json body), need to be separately configured to work with the used json library.
Cats datatypes integration
The tapir-cats
module contains additional instances for some cats
datatypes as well as additional syntax:
"com.softwaremill.sttp.tapir" %% "tapir-cats" % "1.7.5"
import sttp.tapir.integ.cats.codec._
- brings schema, validator and codec instancesimport sttp.tapir.integ.cats.syntax._
- brings additional syntax fortapir
types
Additionally, the tapir-cats-effect
module contains an implementation of the CatsMonadError
class, providing a bridge
between the sttp-internal MonadError
and the cats-effect Sync
typeclass:
"com.softwaremill.sttp.tapir" %% "tapir-cats-effect" % "1.7.5"
Refined integration
If you use refined, the tapir-refined
module will provide implicit codecs and
validators for T Refined P
as long as a codec for T
already exists:
"com.softwaremill.sttp.tapir" %% "tapir-refined" % "1.7.5"
You’ll need to extend the sttp.tapir.codec.refined.TapirCodecRefined
trait or import sttp.tapir.codec.refined._
to bring the implicit values into scope.
The refined codecs contain a validator which wrap/unwrap the value from/to its refined equivalent.
Some predicates will bind correctly to the vanilla tapir Validator, while others will bind to a custom validator that
might not be very clear when reading the generated documentation. Correctly bound predicates can be found in
integration/refined/src/main/scala/sttp/tapir/codec/refined/TapirCodecRefined.scala
.
If you are not satisfied with the validator generated by tapir-refined
, you can provide an implicit
ValidatorForPredicate[T, P]
in scope using ValidatorForPredicate.fromPrimitiveValidator
to build it (do not
hesitate to contribute your work!).
Iron integration
If you use iron, the tapir-iron
module will provide implicit codecs and
validators for T :| P
as long as a codec for T
already exists:
"com.softwaremill.sttp.tapir" %% "tapir-iron" % "1.7.5"
The module is only available for Scala 3 since iron is not designed to work with Scala 2.
You’ll need to extend the sttp.tapir.codec.refined.TapirCodecIron
trait or import sttp.tapir.codec.iron._
to bring the implicit values into scope.
The iron codecs contain a validator which apply the constraint to validated value.
Similarly to tapir-refined
, you can find the predicate logic in integrations/iron/src/main/scala/sttp/iron/codec/iron/TapirCodecIron.scala
and provide your own given ValidatorForPredicate[T, P]
in scope using ValidatorForPredicate.fromPrimitiveValidator
Enumeratum integration
The tapir-enumeratum
module provides schemas, validators and codecs for Enumeratum
enumerations. To use, add the following dependency:
"com.softwaremill.sttp.tapir" %% "tapir-enumeratum" % "1.7.5"
Then, import sttp.tapir.codec.enumeratum._
, or extends the sttp.tapir.codec.enumeratum.TapirCodecEnumeratum
trait.
This will bring into scope implicit values for values extending *EnumEntry
.
NewType integration
If you use scala-newtype, the tapir-newtype
module will provide implicit codecs and
schemas for types with a @newtype
and @newsubtype
annotations as long as a codec and schema for its underlying value already exists:
"com.softwaremill.sttp.tapir" %% "tapir-newtype" % "1.7.5"
Then, import sttp.tapir.codec.newtype._
, or extend the sttp.tapir.codec.newtype.TapirCodecNewType
trait to bring the implicit values into scope.
Monix NewType integration
If you use monix newtypes, the tapir-monix-newtype
module will provide implicit codecs and
schemas for types which extend NewtypeWrapped
and NewsubtypeWrapped
annotations as long as a codec and schema for its underlying value already exists:
"com.softwaremill.sttp.tapir" %% "tapir-monix-newtype" % "1.7.5"
Then, import sttp.tapir.codec.monix.newtype._
, or extend the sttp.tapir.codec.monix.newtype.TapirCodecMonixNewType
trait to bring the implicit values into scope.
ZIO Prelude Newtype integration
If you use ZIO Prelude Newtypes, the tapir-zio-prelude
module will provide implicit codecs and
schemas for types defined using Newtype
and Subtype
as long as a codec and a schema for the underlying type already exists:
"com.softwaremill.sttp.tapir" %% "tapir-zio-prelude" % "1.7.5"
Then, mix in sttp.tapir.codec.zio.prelude.newtype.TapirNewtypeSupport
into your newtype to bring the implicit values into scope:
import sttp.tapir.Codec.PlainCodec
import sttp.tapir.Schema
import sttp.tapir.codec.zio.prelude.newtype.TapirNewtypeSupport
import zio.prelude.Newtype
object Foo extends Newtype[String] with TapirNewtypeSupport[String]
type Foo = Foo.Type
implicitly[Schema[Foo]]
implicitly[PlainCodec[Foo]]
Or use the TapirNewtype
helper to derive a codec or a schema without modifying the newtype:
import sttp.tapir.codec.zio.prelude.newtype.TapirNewtype
object Bar extends Newtype[String]
type Bar = Bar.Type
// Explicitly provide the base type of your newtype when instantiating the helper, in this case, String.
val BarSupport = TapirNewtype[String](Bar)
import BarSupport._
implicitly[Schema[Bar]]
implicitly[PlainCodec[Bar]]
Derevo integration
The tapir-derevo
module provides a way to derive schema for your type using @derive
annotation.
For details refer to derevo documentation.
To use, add the following dependency:
"com.softwaremill.sttp.tapir" %% "tapir-derevo" % "1.7.5"
Then you can derive schema for your ADT along with other typeclasses besides ADT declaration itself:
import derevo.derive
import sttp.tapir.derevo.schema
@derive(schema)
case class Person(name: String, age: Int)
//or with custom description
@derive(schema("Type of currency in the country"))
sealed trait Currency
object Currency {case object CommunisticCurrency extends Currency
case class USD(amount: Long) extends Currency
}
The annotation will simply generate a Schema[T]
for your type T
and put it into companion object.
Generation rules are the same as in Schema.derived[T]
.
This will also work for newtypes — estatico or supertagged:
import derevo.derive
import sttp.tapir.derevo.schema
import io.estatico.newtype.macros.newtype
object types {
@derive(schema)
@newtype
case class Amount(i: Int)
}
Resulting schema will be equivalent to implicitly[Schema[Int]].map(i => Some(types.Amount(i)))
.
Note that due to limitations of the derevo
library one can’t provide custom description for generated schema.
Next
Read on about serving static content.