-
-
Notifications
You must be signed in to change notification settings - Fork 478
Description
Describe the bug
Consider the following type hierarchy:
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 FishWhen 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
Expected behaviour
The schema produced by JsonCodec should be the same one that's produced by zio-json; specifically, the intermediate traits should not be visible in the schema.
Screenshots
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:
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, FishThen the generated schema is correct:
{
"$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?
Full sample code:
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:
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"
)