tapir
tapir copied to clipboard
[BUG] AsyncAPI generated schema issue when using Configuration.withDiscriminator
Tapir version: 1.8.2
Scala version: 3.3.1
AsyncAPI studio can't parse the generated yaml when using Configuration.default.withDiscriminator
for ADT type or simple enum.
Given this minimal example
//> using dep com.softwaremill.sttp.tapir::tapir-zio-http-server:1.8.2
//> using dep com.softwaremill.sttp.tapir::tapir-asyncapi-docs:1.8.2
//> using dep com.softwaremill.sttp.apispec::asyncapi-circe-yaml:0.7.1
//> using dep com.softwaremill.sttp.tapir::tapir-jsoniter-scala:1.8.2
//> using dep "com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:2.24.2"
import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
import sttp.apispec.asyncapi.circe.yaml.*
import sttp.capabilities.zio.ZioStreams
import sttp.tapir.Schema
import sttp.tapir.*
import sttp.tapir.docs.asyncapi.AsyncAPIInterpreter
import sttp.tapir.generic.Configuration
import sttp.tapir.generic.auto.*
import sttp.tapir.json.jsoniter.*
object TapirADT extends App:
val end = endpoint.in("test").out(webSocketBody[Topic, CodecFormat.Json, Topic, CodecFormat.Json](ZioStreams))
val api = AsyncAPIInterpreter().toAsyncAPI(end, "Websocket", "1.0").toYaml
println(api)
sealed trait Topic
object Topic:
sealed trait PublicTopic extends Topic
sealed trait PrivateTopic extends Topic
case object PublicParts extends PublicTopic
case object PrivateParts extends PrivateTopic
given JsonValueCodec[Topic] = JsonCodecMaker.make
given Schema[Topic] = {
given Configuration = Configuration.default.withDiscriminator("type")
Schema.derived[Topic]
}
Which generates this yaml
info:
title: Websocket
version: '1.0'
channels:
/test:
subscribe:
operationId: onTest
message:
$ref: '#/components/messages/Topic'
publish:
operationId: sendTest
message:
$ref: '#/components/messages/Topic'
bindings:
ws:
method: GET
components:
schemas:
Topic:
oneOf:
- $ref: '#/components/schemas/PrivateParts'
- $ref: '#/components/schemas/PublicParts'
discriminator:
propertyName: type
mapping:
PrivateParts: '#/components/schemas/PrivateParts'
PublicParts: '#/components/schemas/PublicParts'
PrivateParts:
required:
- type
type: object
properties:
type:
type: string
PublicParts:
required:
- type
type: object
properties:
type:
type: string
messages:
Topic:
payload:
$ref: '#/components/schemas/Topic'
contentType: application/json
You can see in the attached screenshot that AsyncAPI studio can't parse the generated yaml. The equivalent of this with simple (non websocket) endpoint for OpenAPI works fine while using Configuration.default.withDiscriminator
.