我有一个案例类,其中一些逻辑约束require在案例类主体中作为 s 实现。当尝试从表示语法正确但逻辑上无效的实例的 JSON 中解码此案例类时,异常实际上是在调用线程上引发的,而不是作为Leftfrom的返回decode。
重现代码片段:
case class Foo(bar: String) {
require(bar.length < 5)
}
object Sandbox extends App {
import io.circe.generic.auto._
import io.circe.parser._
val foo1 = decode[Foo](""" {"bar":"abc"} """)
println(s"foo1: $foo1")
//expected: Left(IllegalArgumentException("requirement failed"))
//actual: throws IllegalArgumentException("requirement failed")
val foo2 = decode[Foo](""" {"bar":"abcdefg"} """)
println(s"foo2: $foo2")
}
Run Code Online (Sandbox Code Playgroud)
是否可以让此异常返回而不Left抛出decode?欢迎任何想法/建议...
TIA
M。
使用精炼在有约束的情况下自动派生这些编解码器。
或者,如果您想验证 JSON 但不验证构造函数,您可以随时调整编解码器,例如
case class Foo(bar: String)
object Foo {
implicit val decoder: Decoder[Foo] = deriveDecoder[Foo].emapTry(foo =>
Try(require(foo.bar.length < 5))
)
}
Run Code Online (Sandbox Code Playgroud)
有时您还可以使用中间类型进行推导并映射它:
case class Foo(bar: String) {
require(bar.length < 5)
}
object Foo {
// allows usage of derivation, especially if you would derive several typeclasses
// and then adjust their behavior
private case class FooHelper(bar: String)
implicit val decoder: Decoder[Foo] = deriveDecoder[FooHelper].emapTry(helper =>
Try(Foo(helper.foo))
)
}
Run Code Online (Sandbox Code Playgroud)
一般来说,我建议不要使用require,特别是在构造函数中,而使用智能构造函数。
sealed abstract case class Foo private (bar: String)
object Foo {
def parse(bar: String): Either[String, Foo] =
if (bar.length < 5) Right(new Foo(bar) {})
else Left(s"Invalid bar value: $bar")
def parseUnsafe(bar: String): Foo =
parse(bar).fold(error => throw new Exception(error), foo => foo)
private case class FooHelper(bar: String)
implicit val decoder: Decoder[Foo] = deriveDecoder[FooHelper].emapTry(helper =>
Try(parseUsafe(helper.foo))
)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
456 次 |
| 最近记录: |