我正在努力在特定用例中使用提取器模式,似乎它可能非常强大。
我从Web请求的Map [String,String]输入开始。这是对我们的api的searchRequest或countRequest。
searchRequest有密钥
countRequest有键
然后,我想将这两者转换为像这样的组合类型结构
protected case class CommonQueryRequest(
originalQuery: String,
fromDate: DateTime,
toDate: DateTime
)
case class SearchQueryRequest(
commonRequest: CommonQueryRequest,
maxResults: Int,
nextToken: Option[Long])
case class CountRequest(commonRequest: CommonQueryRequest, bucket: String)
正如你所看到的,我将字符串转换为DateTimes和Int,Long等等。我的问题是我真的需要将无效的fromDate与无效的toDate格式与无效的maxResults与无效的下一个令牌IF可用相关的错误
与此同时,我需要坚持默认值(根据搜索或计数请求的不同而不同)。
当然,随着Map的传入,你可以告诉搜索与计数,所以在我第一次看到这个时,我添加了一个key =“type”,其值为search或count,这样我至少可以匹配
我甚至走错了路吗?我想也许使用匹配可能比我们现有的实现更清晰,但是我走得更远,这看起来有点丑陋。
感谢, 迪安
答案 0 :(得分:2)
我建议你看看scalaz.Validation和ValidationNel。它是收集验证错误的超级好方法,非常适合输入请求验证。
您可以在此处详细了解验证:http://eed3si9n.com/learning-scalaz/Validation.html。但是在我的示例中,我使用的是scalaz 7.1,它可能与本文中描述的略有不同。然而,主要观点仍然相同。
以下是用例的小例子:
import java.util.NoSuchElementException
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import scala.util.Try
import scalaz.ValidationNel
import scalaz.syntax.applicative._
import scalaz.syntax.validation._
type Input = Map[String, String]
type Error = String
case class CommonQueryRequest(originalQuery: String,
fromDate: DateTime,
toDate: DateTime)
case class SearchQueryRequest(commonRequest: CommonQueryRequest,
maxResults: Int,
nextToken: Option[Long])
case class CountRequest(commonRequest: CommonQueryRequest, bucket: String)
def stringField(field: String)(input: Input): ValidationNel[Error, String] =
input.get(field) match {
case None => s"Field $field is not defined".failureNel
case Some(value) => value.successNel
}
val dateTimeFormat = DateTimeFormat.fullTime()
def dateTimeField(field: String)(input: Input): ValidationNel[Error, DateTime] =
Try(dateTimeFormat.parseDateTime(input(field))) recover {
case _: NoSuchElementException => DateTime.now()
} match {
case scala.util.Success(dt) => dt.successNel
case scala.util.Failure(err) => err.toString.failureNel
}
def intField(field: String)(input: Input): ValidationNel[Error, Int] =
Try(input(field).toInt) match {
case scala.util.Success(i) => i.successNel
case scala.util.Failure(err) => err.toString.failureNel
}
def countRequest(input: Input): ValidationNel[Error, CountRequest] =
(
stringField ("query") (input) |@|
dateTimeField("fromDate")(input) |@|
dateTimeField("toDate") (input) |@|
stringField ("bucket") (input)
) { (query, from, to, bucket) =>
CountRequest(CommonQueryRequest(query, from, to), bucket)
}
val validCountReq = Map("query" -> "a", "bucket" -> "c")
val badCountReq = Map("fromDate" -> "invalid format", "bucket" -> "c")
println(countRequest(validCountReq))
println(countRequest(badCountReq))
答案 1 :(得分:0)