Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider adding "title" to Schema automatically #3447

Closed
adamw opened this issue Jan 10, 2024 · 1 comment · Fixed by #3593
Closed

Consider adding "title" to Schema automatically #3447

adamw opened this issue Jan 10, 2024 · 1 comment · Fixed by #3593
Assignees

Comments

@adamw
Copy link
Member

adamw commented Jan 10, 2024

Or at least to hierarchy members.

See: https://stackoverflow.com/questions/77739438/generate-right-schema-and-documentation-with-tapir-and-sealed-traits

@dacr
Copy link

dacr commented Jan 24, 2024

The workaround for scala 3 context inspired from the stackoverflow : given Schema[Message] = Schema.derived[Message].title(classOf[Message].getSimpleName)

It would be interesting I think to avoid all those givens by having those title set automatically.

A runnable snippet example with the workwaround :

// ---------------------
//> using scala "3.3.1"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio:1.9.6"
//> using dep "com.softwaremill.sttp.tapir::tapir-json-zio:1.9.6"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio-http-server:1.9.6"
//> using dep "com.softwaremill.sttp.tapir::tapir-swagger-ui-bundle:1.9.6"
// ---------------------

import zio.*
import zio.http.Server
import zio.json.{JsonCodec, jsonDiscriminator}
import sttp.tapir.json.zio.*
import sttp.tapir.ztapir.*
import sttp.tapir.server.ziohttp.ZioHttpInterpreter
import sttp.apispec.openapi.Info
import sttp.tapir.Schema
import sttp.tapir.generic.Configuration
import sttp.tapir.swagger.bundle.SwaggerInterpreter
import sttp.tapir.generic.auto.*

/*
curl -L http://127.0.0.1:8080/docs
 */

@jsonDiscriminator("@kind")
sealed trait Feedback derives JsonCodec
case class Message(text: String) extends Feedback derives JsonCodec

@jsonDiscriminator("@kind")
sealed trait Greetings derives JsonCodec
case class Simple(message: Feedback)            extends Greetings derives JsonCodec
case class Polite(tile: Int, message: Feedback) extends Greetings derives JsonCodec

object WebApp extends ZIOAppDefault {
  implicit val tapirConfig: Configuration =
    Configuration.default
      .withDiscriminator("@kind")
  // .withSnakeCaseMemberNames
  // .withKebabCaseDiscriminatorValues

  // ----------------------------------------------------
  // see https://github.com/softwaremill/tapir/issues/3476
  // see https://stackoverflow.com/questions/77739438/generate-right-schema-and-documentation-with-tapir-and-sealed-traits
  given Schema[Message] = Schema.derived[Message].title(classOf[Message].getSimpleName)
  given Schema[Simple]  = Schema.derived[Simple].title(classOf[Simple].getSimpleName)
  given Schema[Polite]  = Schema.derived[Polite].title(classOf[Polite].getSimpleName)
  // ----------------------------------------------------

  val helloEndPoint =
    endpoint
      .description("say hello")
      .get
      .in("hello")
      .out(jsonBody[Feedback])

  val helloRoute = helloEndPoint.zServerLogic[Any](_ => ZIO.succeed(Message("Hello")))

  // --------------------------------------------------
  val greetingEndPoint =
    endpoint
      .description("Return random greeting")
      .get
      .in("greeting")
      .out(jsonBody[Greetings])

  val greetings = List[Greetings](
    Simple(Message("Hi")),
    Simple(Message("Hello")),
    Polite(30, Message("Nice to meed you"))
  )

  val greetingRoute = greetingEndPoint.zServerLogic[Any](_ => Random.shuffle(greetings).map(_.head))

  // --------------------------------------------------

  val docEndpoints =
    SwaggerInterpreter()
      .fromServerEndpoints(
        List(helloRoute, greetingRoute),
        Info(title = "Greeting API", version = "1.0", description = Some("Everything required to be polite"))
      )

  // --------------------------------------------------

  val routes = ZioHttpInterpreter().toHttp(List(helloRoute, greetingRoute) ++ docEndpoints)

  // --------------------------------------------------

  override def run =
    Server
      .serve(routes)
      .provide(Server.default)
}

WebApp.main(Array.empty)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants