Skip to main content
Version: 2.x

Transforming Schemas

Using the Schema#transform method, we can transform a Schema[A] into a Schema[B] by supplying two functions that can transform between A and B. In normal Scala code this would be the equivalent of map, but with isomorphism property.

object Schema {
def transform[B](f: A => B, g: B => A): Schema[B] = ???
}

Therefore, if we have a schema for A, and isomorphism between A and B, we can derive a schema for B in terms of `Schema[A].

note

In type theory, isomorphism refers to a relationship between two types that have a bijective correspondence or mapping between their elements. More specifically, if two types, let's say Type A and Type B, are isomorphic, it means that there exists a pair of functions—one going from A to B (often called the forward function) and another going from B to A (often called the backward function)—that satisfy certain properties.

In ZIO Schema this is modelled by the Transform type class:

object Schema {
final case class Transform[A, B](
codec: Schema[A],
f: A => Either[String, B],
g: B => Either[String, A]
) extends Schema[B]
}

For example, assume we have a wrapper class Age that wraps an Int value, and it has some validation logic, e.g. the age must be between 0 and 120. We can define a Schema[Age] by using the Schema.transform method:

import zio.schema._

case class Age(i: Int)

object Age {
implicit val schema: Schema[Age] =
Schema[Int].transformOrFail(
(i: Int) =>
if (i >= 0 && i <= 120)
Right(Age(i))
else
Left("Age must be between 1 and 120"),
(age: Age) => Right(age.i)
)
}