softwaremill / softwaremill/tapir

[BUG] AsyncAPI generated schema issue when using Configuration.withDiscriminator

Open
#3,275 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
1.5k
Forks
468
Avg merge
5h 37m
Merged PRs (30d)
34

Description

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.

Screenshot 2023-10-26 at 10 24 35

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the supplied Scala 3.3.1 reproduction with AsyncAPIInterpreter().toAsyncAPI and inspect the generated YAML around the discriminator schema. Compare the AsyncAPI output with the working OpenAPI behavior and verify the result in AsyncAPI Studio. Done means the generated YAML parses successfully while discriminator support for ADTs and simple enums remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.