Skip to content

OpenAPI generator ignores @discriminatorName and @caseName annotations for sealed traits #3868

@wi101

Description

@wi101

Describe the bug
When using zio-schema annotations (@discriminatorName, @caseName, @fieldName) on a sealed trait to define a discriminated union, the generated OpenAPI spec does not produce the expected oneOf with discriminator structure.

To Reproduce

import zio.http._
import zio.http.endpoint.Endpoint
import zio.http.endpoint.openapi.OpenAPIGen
import zio.schema.annotation.{caseName, discriminatorName, fieldName}
import zio.schema.{DeriveSchema, Schema}
import java.time.Instant

@discriminatorName("status")
sealed trait UserStatus

object UserStatus {
  @caseName("online")
  case class Online(d: Instant) extends UserStatus

  @caseName("offline")
  case class Offline(d: Instant) extends UserStatus

  @caseName("away")
  final case class Away(@fieldName("minutes") idleMinutes: Int) extends UserStatus

  implicit val schema: Schema[UserStatus] = DeriveSchema.gen[UserStatus]
}

case class User(name: String, status: UserStatus)
object User {
  implicit val schema: Schema[User] = DeriveSchema.gen[User]
}

// Endpoint using the types
val example = Endpoint(Method.POST / "example")
  .in[User]
  .out[UserStatus](Status.Ok)

// Generate OpenAPI
val openAPI = OpenAPIGen.fromEndpoints("Example API", "1.0.0", example)
println(openAPI.toJson)

api.yaml:

UserStatus:
  oneOf:
    - $ref: '#/components/schemas/Online'
    - $ref: '#/components/schemas/Offline'
    - $ref: '#/components/schemas/Away'
  discriminator:
    propertyName: status
    mapping:
      online: '#/components/schemas/Online'
      offline: '#/components/schemas/Offline'
      away: '#/components/schemas/Away'

    Offline:
      type: object
      properties:
        d:
          type: string
      required:
        - d
    Online:
      type: object
      properties:
        d:
          type: string
      required:
        - d
    Away:
      type: object
      properties:
        minutes:
          type: integer
          format: int32 
        

Note: But the referenced case schemas (Online, Offline, Away) are missing the discriminator property status:

Expected behaviour

Online:
  type: object
  properties:
    status:
      type: string
      enum: [online]
    d:
      type: string
  required:
    - status
    - d
...

Screenshots

Input (incorrect):

Image

Output (correct):

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions