考虑一个
tapir.Codec
对象(这就是我遇到这个问题的方式,但我认为它与貘具体没有太大关系,它只是一般来说隐式解析优先级),它定义了一堆编解码器基本类型,如 Codec.long
、Codec.int
等
我试图定义一种“后备”编解码器,可以在找不到标准编解码器时使用(IRL,类型比仅仅
T
更具体,但实际实现在这里并不重要):
implicit def fallbackCodec[T]: Codec[String, T, PlainText] = ???
但我不知道该定义在哪里。 我尝试将它添加到我正在扩展的特征之一,或者添加到它自己的特征中,由其他特征扩展,或者添加到它自己的对象中,然后在调用站点导入
Fallback._
...
无论我做什么,
in(path[Foo]("foo"))
都工作得很好,但是in(path[Long]("id"))
also最终使用我的后备编解码器而不是Codec.long
我在想,由于标准编解码器是在伴随对象中定义的,因此它们会胜过我的自定义定义,但看起来情况并非如此。我是否缺少一些技巧来让它达到我想要的效果?
好吧,我想,我找到了一个解决方案,将其留在这里,以防其他人发现它有帮助。 这似乎有效:
trait FallbackCodecs {
implicit def plaintextCodec[T]: Codec[String, T, TextPlain] = ???
}
trait DefaultCodecs extends FallbackCodecs {
implicit def defaultCodec[T](implicit c: Lazy[Codec[String, T, TextPlain]]) = c.value
}
class FooBar extends DefaultCodecs {
def foo[T](implicit c: Codec[String, T, TextPlain]) = println(c)
foo[Int] // Codec.int
foo[Foo] // plaintextCodec
}
另一种可能性,也有效,但不必定义
defaultCodec
并具有额外的特征,那就是显式地
import sttp.tapir.Codec._
在FooBar
。
它有点脆弱,因为如果 FooBar 的作者忘记添加显式导入,它将编译,并用后备默默地替换所有编解码器。此外,它还会生成“未使用的导入”警告。
您可以使用
shapeless.LowPriority
//libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.10"
implicit def fallbackCodec[T](implicit lowPriority: LowPriority): Codec[String, T, TextPlain] = ???