2

对于我的一条路线,我有一个可选参数birthDate: Option[String],即可以这样做:

GET /rest/api/findSomeone/:firstName/:lastName controllers.PeopleController.findSomeone(firstName: String, lastName: String, birthDate: Option[String])

但是,要对可选参数更加严格,birthDate指定这样的正则表达式会很有帮助:

$birthDate<([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))>

但是由于这是一个可选参数,我找不到这样做的方法.. Play 2.7.x 中涵盖了它吗?我面临着使birthDate参数成为非可选参数或不选中它的两难境地。

作为旁注。我一直在尝试集成 Joda 时间的路由绑定,例如org.joda.time.LocalDate通过添加以下依赖项https://github.com/tototoshi/play-joda-routes-binder "com.github.tototoshi" %% "play-joda-routes-binder" % "1.3.0"但它在我的项目中不起作用,因为我在集成后遇到编译错误所以我暂时把这种方法藏起来了。

4

1 回答 1

2

对于解析日期,我根本不建议使用基于正则表达式的验证器。相反,您可以 - 例如 - 使用带有查询字符串绑定器的自定义案例类,它将对传入参数进行类型安全的解析:

package models

import java.time.LocalDate
import java.time.format.{DateTimeFormatter, DateTimeParseException}

import play.api.mvc.QueryStringBindable

case class BirthDate(date: LocalDate)

object BirthDate {
  private val dateFormatter: DateTimeFormatter = DateTimeFormatter.ISO_DATE // or whatever date format you're using

  implicit val queryStringBindable = new QueryStringBindable[BirthDate] {
    override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, BirthDate]] = {
      params.get(key).flatMap(_.headOption).map { value =>
        try {
          Right(BirthDate(LocalDate.parse(value, dateFormatter)))
        } catch {
          case _: DateTimeParseException => Left(s"$value cannot be parsed as a date!")
        }
      }
    }

    override def unbind(key: String, value: BirthDate): String = {
      s"$key=${value.date.format(dateFormatter)}"
    }
  }
}

现在,如果您更改您的路线配置,因此birthDate是 type 的参数Option[BirthDate],您将获得您想要的行为。

如果您坚持使用正则表达式,您可以使用基于正则表达式的解析器来代替日期格式化程序并使用BirthDatewrap aString而不是 a LocalDate,但是对于所呈现的用例,我真的看不出这样做的好处是什么.

编辑:为了完整起见,基于正则表达式的变体:

case class BirthDate(date: String)

object BirthDate {
  private val regex = "([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))".r

  implicit val queryStringBindable = new QueryStringBindable[BirthDate] {
    override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, BirthDate]] = {
      params.get(key).flatMap(_.headOption).map { value =>
        regex.findFirstIn(value).map(BirthDate.apply).toRight(s"$value cannot be parsed as a date!")
      }
    }

    override def unbind(key: String, value: BirthDate): String = {
      s"$key=${value.date}"
    }
  }
}
于 2019-06-07T10:19:00.110 回答