[英]Error Accumulation with Scalaz Validation
我有一个复杂的JSON,它已存储在数据库中。 它的复杂性在“块”中“隔离”,如下所示:
整个JSON:
{
"block1" : {
"param1" : "val1",
"param2" : "val2"
},
"block2" : {
"param3" : "val3",
"param4" : "val4"
},
...
}
在数据库中,每个块均被存储和单独处理:
持久块
"block1" : {
"param1" : "val1",
"param2" : "val2"
}
"block2" : {
"param3" : "val3",
"param4" : "val4"
}
每个块都有业务含义,因此,每个块都映射到一个案例类。 我正在构建一个Play API,用于存储,更新和检索此JSON结构,并且我想验证是否有人为了完整性而更改了它的数据。
我正在对每个块进行检索(解析和验证),如下所示:
val block1 = Json.parse(block1).validate[Block1].get
val block2 = Json.parse(block2).validate[Block2].get
...
案例类:
trait Block
sealed case class Block1 (param1: String, param2: String, ...) extends Block
sealed case class Block2 (param3: String, param4: String, ...) extends Block
sealed case class Request (block1: Block1, block2: Block2, ...)
在当前结构下,如果某些字段被更改且与定义的类型不匹配,则Play抛出此异常:
[NoSuchElementException:JsError.get]
因此,我想使用Scalaz和Validation建立一个累积的错误结构,以捕获所有可能的解析和验证错误。 我已经看到了这 一点,因此我以这种方式编写了验证代码:
def build(block1: String, block2: String, ...): Validation[NonEmptyList[String], Request] = {
val block1 = Option(Json.parse(block1).validate[Block1].get).toSuccess("Error").toValidationNel
val block2 = Option(Json.parse(block2).validate[Block2].get).toSuccess("Error").toValidationNel
...
val request = (Request.apply _).curried
blockn <*> (... <*> (... <*> (...<*> (block2 <*> (block1 map request)))))
}
请注意,我使用的是应用函子<*>
因为Request
具有20个字段(使用该语法的圆括号), |@|
适用函子仅适用于最多12个参数的案例类。
该代码适用于幸福的道路,但是,当我修改某些字段时,Play会引发稍后描述的Execution Exception。
问题 :我想积累在解析每个块时Play可以检测到的所有可能的结构故障。 我怎样才能做到这一点?
注意 :如果Shapeless在某种程度上与此有关,我愿意使用它(我已经在使用它)。
如果多重验证是向您的项目中添加Scalaz的唯一原因,那么为什么不考虑一种替代方案,它不需要您将Play项目适应于Scalaz强迫您解决问题的单子方式(这也许是一件好事,但是不一定(如果唯一的原因是多重验证)。
而是考虑将标准Scala方法与scala.util.Try
:
val block1 = Try(Json.parse(block1).validate[Block1].get)
val block2 = Try(Json.parse(block2).validate[Block2].get)
...
val allBlocks : List[Try[Block]] = List(block1, block2, ...)
val failures : List[Failure[Block]] = allBlocks.collect { case f : Failure[Block] => f }
这样,您仍然可以对标准Scala集合进行操作,以检索要进一步处理的故障列表。 同样,此方法也不会限制块的数量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.