Automatic derivation of ZIO Prelude New Types

Been struggling to do Automatic derivation of classes encoded with ZIO prelude’s newtypes. Here is a full code lists that can be reproduced in a scala worksheet

import sttp.tapir._
import sttp.tapir.generic.auto._
import sttp.tapir.json.zio.jsonBody
import sttp.tapir.ztapir.ZServerEndpoint
import zio.ZIO
import zio.json._
import zio.prelude.Newtype

object Name extends Newtype[String] {
  implicit val codec: JsonCodec[Type] = derive
}
type Name = Name.Type

case class Person(name: Name)

object Person {
  implicit val encoder: zio.json.JsonEncoder[Person] = DeriveJsonEncoder.gen[Person]
  implicit val decoder: zio.json.JsonDecoder[Person] = DeriveJsonDecoder.gen[Person]
}

object PersonRoute {

  val persons = List(Person(Name("John")),Person(Name("Jane")))

  private val personListEndPoint: PublicEndpoint[Unit, Unit, List[Person], Any] =
    endpoint.get
      .in("user" / "one" )
      .out(jsonBody[List[Person]])
  val personsListingServerEndpoint: ZServerEndpoint[Any, Any]        =
    personListEndPoint.serverLogicSuccess(_ => ZIO.succeed(persons))
}

When run I get the error below with the suggestions, but I already implemented the suggestion

ould not find Schema for type List[A$A0.this.Person].
Automatic derivation requires the following import: `import sttp.tapir.generic.auto._`
You can find more details in the docs: https://tapir.softwaremill.com/en/latest/endpoint/schemas.html#schema-derivation
When using datatypes integration remember to import respective schemas/codecs as described in https://tapir.softwaremill.com/en/latest/endpoint/integrations.html
      .out(jsonBody[List[Person]])

What would be the workaround this? Though the error message is not helpful, it seems the encoding/decoding of the ZIO Prelude newtype is the real issue at play here and tried a number of combinations with no success.

Hi,
you can add "com.softwaremill.sttp.tapir" %% "tapir-zio-prelude" % "VERSION" dependency to your project.

Once added, you will be able to use TapirNewtypeSupport trait to provide tapir codec and schema for your new type.

Usage looks like that:

object Name extends Newtype[String] with TapirNewtypeSupport[String]

Thanks, Damian, it works. I must say that Tapir is quite extensive.

Now I have to think about how I solve the other incidental issues that arise from the suggested approach. Do I want the large domain model to have tapir everywhere or is there a way I can abstract the solution away? I need to make the solution easy to change or replace.

Once again thanks

As an alternative, you can define codecs and schemas by hand, like that:

implicit val codec = TapirNewtype[String](Name).tapirCodec[String, CodecFormat.TextPlain]
implicit val schema = TapirNewtype[String](Name).tapirSchema

and then place them in an object that’s separate from your domain models definitions