`JsonCodec.jsonCodec` produces inconsistent schema when type hierarchy has nested `sealed trait`s
bug
**Describe the bug**
Consider the following type hierarchy:
```scala
sealed trait Animal derives JsonCodec, Schema
sealed trait Dog extends Animal
sealed trait Fish extends Animal
case class GoldenRetriever(name: String) extends Dog
case class Bass(color: String) extends Fish
```
When using `zio-json`, instances are discriminated by their instance class name.
When using `zio-http` with `zio-schema`, generating the json schema via `JsonCodec.jsonCodec[Schema[Animal]]` produces a json schema where `Animal` is first discriminated by `Dog` or `Fish`.
**To Reproduce**
Steps to reproduce the behaviour:
[Scastie link
](https://scastie.scala-lang.org/UQliolhTSzWJdS6Dxsc9Ww)
**Expected behaviour**
The schema produced by `JsonCodec` should be the same one that's produced by `zio-json`; specifically, the intermediate `trait`s should not be visible in the schema.
**Screenshots**
<img width="867" height="787" alt="Image" src="https://github.com/user-attachments/assets/a82fb98b-6595-4ac1-931a-b0be53d38fe0" />
**Additional context**
For context, I was trying to generate a spec (json/openapi) that I could feed to an LLM so it could understand/build values of type `Animal` for me.
A workaround (though kind of ugly) is to NOT extend `Animal` in the intermediate traits:
```scala
sealed trait Animal derives JsonCodec, Schema
sealed trait Dog { self: Animal => }
sealed trait Fish { self: Animal => }
case class GoldenRetriever(name: String) extends Animal, Dog
case class Bass(color: String) extends Animal, Fish
```
Then the generated schema is correct:
```json
{
"$schema" : "https://json-schema.org/draft/2020-12/schema",
"oneOf" : [
{
"type" : "object",
"properties" : {
"GoldenRetriever" : {
"$ref" : "#/$defs/GoldenRetriever"
}
},
"additionalProperties" : false,
"required" : [
"GoldenRetriever"
]
},
{
"type" : "object",
"properties" : {
"Bass" : {
"$ref" : "#/$defs/Bass"
}
},
"additionalProperties" : false,
"required" : [
"Bass"
]
}
],
"$defs" : {
"GoldenRetriever" : {
"type" : "object",
"properties" : {
"name" : {
"type" : "string"
}
},
"required" : [
"name"
]
},
"Bass" : {
"type" : "object",
"properties" : {
"color" : {
"type" : "string"
}
},
"required" : [
"color"
]
}
}
}
```
I wonder if this issue has a similar underlying cause as [one I previously reported](https://github.com/zio/zio-http/issues/3801)?
Full sample code:
```scala
import zio.*
import zio.json.*
import zio.json.ast.*
import zio.schema.*
import zio.schema.codec.*
import zio.schema.codec.json.*
import zio.http.endpoint.openapi.*
sealed trait Animal derives JsonCodec, Schema
sealed trait Dog extends Animal
sealed trait Fish extends Animal
case class GoldenRetriever(name: String) extends Dog
case class Bass(color: String) extends Fish
val animal: Animal = Bass("brown")
// produces:
// {"Bass":{"color":"brown"}}
println(animal.toJson)
val jsonSchema = JsonSchema.jsonSchema(Schema[Animal])
// produces:
//{
// "$schema" : "https://json-schema.org/draft/2020-12/schema",
// "oneOf" : [
// {
// "type" : "object",
// "properties" : {
// "Dog" : {
// "$ref" : "#/$defs/Dog"
// }
// },
// "additionalProperties" : false,
// "required" : [
// "Dog"
// ]
// },
// {
// "type" : "object",
// "properties" : {
// "Fish" : {
// "$ref" : "#/$defs/Fish"
// }
// },
// "additionalProperties" : false,
// "required" : [
// "Fish"
// ]
// }
// ],
// "$defs" : {
// "GoldenRetriever" : {
// "type" : "object",
// "properties" : {
// "name" : {
// "type" : "string"
// }
// },
// "required" : [
// "name"
// ]
// },
// "Dog" : {
// "oneOf" : [
// {
// "type" : "object",
// "properties" : {
// "GoldenRetriever" : {
// "$ref" : "#/$defs/GoldenRetriever"
// }
// },
// "additionalProperties" : false,
// "required" : [
// "GoldenRetriever"
// ]
// }
// ]
// },
// "Bass" : {
// "type" : "object",
// "properties" : {
// "color" : {
// "type" : "string"
// }
// },
// "required" : [
// "color"
// ]
// },
// "Fish" : {
// "oneOf" : [
// {
// "type" : "object",
// "properties" : {
// "Bass" : {
// "$ref" : "#/$defs/Bass"
// }
// },
// "additionalProperties" : false,
// "required" : [
// "Bass"
// ]
// }
// ]
// }
// }
//}
println(jsonSchema.toJsonPretty)
```
with the following `build.sbt`:
```scala
scalaVersion := "3.7.4"
libraryDependencies ++= Seq(
"org.scastie" %% "runtime-scala" % "1.0.0-SNAPSHOT",
"dev.zio" %% "zio-json" % "0.8.0",
"dev.zio" %% "zio" % "2.1.24",
"dev.zio" %% "zio-schema-json" % "1.7.6",
"dev.zio" %% "zio-http" % "3.8.1",
"dev.zio" %% "zio-schema" % "1.7.6"
)
scalacOptions ++= Seq(
"-deprecation",
"-encoding", "UTF-8",
"-feature",
"-unchecked"
)
```
关闭于 2026-03-03 0 条评论