tapir
tapir copied to clipboard
Derived schema name for `List[T]` is `scala.collection.immutable.:: [BUG]
Tapir version: 1.7.3
Scala version: 2.12.15
When deriving a List[T] where T is defined inside of a companion object, the generated schema for List[T] is scala.collection.immutable.:: { head, tl }
How to reproduce?
import sttp.tapir.Schema
import sttp.tapir.generic.auto._
object TestSchema extends App {
case class Container(values: List[Container.Value])
object Container {
case class Value(key: String, value: String)
}
case class Root(containers: List[Container])
val s = implicitly[Schema[Root]]
println(s.show)
}
This prints:
schema is SProduct(List(SProductField(FieldName(containers,containers),Schema(SArray(Schema(SProduct(List(SProductField(FieldName(values,values),Schema(SCoproduct(List(Schema(SProduct(List(SProductField(FieldName(head,head),Schema(SProduct(List(SProductField(FieldName(key,key),Schema(SString(),None,false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))), SProductField(FieldName(value,value),Schema(SString(),None,false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))))),Some(SName(whoco.sourcing.services.chat.TestSchema.Container.Value,List())),false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))), SProductField(FieldName(tl,tl),Schema(SRef(SName(scala.collection.immutable.List,List(Value))),None,false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))))),Some(SName(scala.collection.immutable.::,List(Value))),false,None,None,None,None,false,false,All(List()),AttributeMap(Map())), Schema(SProduct(List()),Some(SName(scala.collection.immutable.Nil,List())),false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))),None),Some(SName(scala.collection.immutable.List,List(Value))),false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))))),Some(SName(whoco.sourcing.services.chat.TestSchema.Container,List())),false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))),None,true,None,None,None,None,false,false,All(List()),AttributeMap(Map())))))
Note the references to the implementation details of Scala List.
Which tapir and Scala version are you using? I'm getting
schema is SProduct(List(SProductField(FieldName(containers,containers),Schema(SArray(Schema(SProduct(List(SProductField(FieldName(values,values),Schema(SArray(Schema(SProduct(List(SProductField(FieldName(key,key),Schema(SString(),None,false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))), SProductField(FieldName(value,value),Schema(SString(),None,false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))))),Some(SName(sttp.tapir.examples3.Test.Container.Value,List())),false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))),None,true,None,None,None,None,false,false,All(List()),AttributeMap(Map()))))),Some(SName(sttp.tapir.examples3.Test.Container,List())),false,None,None,None,None,false,false,All(List()),AttributeMap(Map()))),None,true,None,None,None,None,false,false,All(List()),AttributeMap(Map())))))
which seems correct (Scala 3.3.0, latest tapir)
Hmm, guessing it might be related to Scala version then. Here's what I'm using:
Tapir version: 1.7.3
Scala version: 2.12.15
I can also try with 2.13 when I'm back online tomorrow.
Indeed this seems to be broken on 2.12 only. 2.13 works fine. Must be something with implicit resolution, but what exactly, no idea ... is the "inside of companion object" an important variable here? (that is, does it work fine if the classes are defined at the top level)
Yes, if we make Value a top-level class then we don't see the issue (that has been our work-around so far).
Another potential clue I can provide is that if I change case class Root(containers: List[Container]) to not take a List[Container], but just a single value, then the issue doesn't happen anymore, eg this works ok:
object TestSchema extends App {
case class Container(values: List[Container.Value])
object Container {
case class Value(key: String, value: String)
}
case class Root(container: Container)
val s = implicitly[Schema[Root]]
println(s.show)
}
Ok, thanks for the report, but since that's a rather old Scala version, I doubt that we'll get to investigating this any time soon. So if there's a work-around that's great, another option would be update to 2.13 / 3 :)
Sounds good, and appreciated. Yeah getting on 2.13 has been one of our goals so maybe we should prioritize that :)