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

Snake case and discriminator config ignored #3904

Open
axaluss opened this issue Jul 5, 2024 · 5 comments
Open

Snake case and discriminator config ignored #3904

axaluss opened this issue Jul 5, 2024 · 5 comments

Comments

@axaluss
Copy link

axaluss commented Jul 5, 2024

Tapir version: 1.10.12

Scala version: 2.13

I created a simple http post endpoint that receives a json request and produces a json response. It uses schema derivation to map the request and response to case classes.
i added implicit config to use discrinator and snake case members

‘’’

implicit val customConfiguration: Configuration =
Configuration.default.withDiscriminator(“type_discriminator”).withSnakeCaseMemberNames
‘’’

What is the problem?

The discriminator and snake case work in openapi spec generation but they are completely ignored for zio http server interpretation https://tapir.softwaremill.com/en/latest/server/ziohttp.html

How to reproduce?
Apply the implicit config to a tapir endpoint with schema/json derivation and run it in zio server interpreter.

Maybe you can provide code to reproduce the problem?

Additional information

@adamw
Copy link
Member

adamw commented Jul 5, 2024

Which JSON library are you using to perform the deserialisation?

You need to configure both tapir & the JSON codec separately, see: https://tapir.softwaremill.com/en/latest/endpoint/json.html

@axaluss
Copy link
Author

axaluss commented Jul 5, 2024

i am using circe.
I think I figured it out.

I had to make sure the Configurations are of the right package.

object MyTapirJsonCirce  extends TapirJsonCirce {
  implicit lazy val customTapirSchemaConfig: sttp.tapir.generic.Configuration =
    sttp.tapir.generic.Configuration.default
      .withDiscriminator("type_discriminator")
      .withSnakeCaseMemberNames

  implicit lazy val customCirceJsonConfig: io.circe.generic.extras.Configuration =
    io.circe.generic.extras.Configuration.default
      .withDiscriminator("type_discriminator")
      .withSnakeCaseMemberNames
}

Then I also had to figure out the right import incantation such that the implicits align in just the right way to work... not sure which of these are actually needed.

...
import io.circe._
import io.circe.syntax._
import io.circe.generic.extras._
import io.circe.generic.extras.auto._
import sttp.tapir.Codec.JsonCodec
import sttp.tapir.Schema
import sttp.tapir.generic.auto._
import MyTapirJsonCirce._

val theEndpoint: Endpoint[Unit, Request, ErrorResponse, Response, Any] =
      endpoint
        .in("product")
        .in("events")
        .post
        .in(EndpointInput.derived[Request])
        .out(EndpointOutput.derived[Response])

case class Request(
        @jsonbody
        event:                            Event,
        @query accountId:                 String)
    sealed trait Event
    case class CreateUpdate(
        adminGraphqlApiId: String)
        extends Event

@axaluss
Copy link
Author

axaluss commented Jul 6, 2024

It may be beneficial to have a documented nontrivial example of this use case of snake case + discriminator

@adamw
Copy link
Member

adamw commented Jul 7, 2024

There's an example here on how to use discriminators:

// the CirceConfiguration class is a renamed import (see above), as the name would clash with tapir's Configuration

I'm currently working on having these examples better visible and discoverable :)

@adamw
Copy link
Member

adamw commented Jul 7, 2024

As for the improts, you need the import MyTapirJsonCirce._ as it brings into scope the configuraton (which is used during the EndpointInput.derived[Request] call), and the import io.circe.generic.extras.auto._ + import sttp.tapir.generic.auto._ to automatically derive the codec/schema. I don't think the others are needed.

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

No branches or pull requests

2 participants