【问题标题】:Scala Play: Routes optional parameter with regex?Scala Play:使用正则表达式路由可选参数?
【发布时间】:2019-06-07 09:18:51
【问题描述】:

对于我的一条路线,我有一个可选参数,即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 time 的路由绑定,例如org.joda.time.LocalDate 通过添加以下依赖项 https://github.com/tototoshi/play-joda-routes-binder "com.github.tototoshi" %% "play-joda-routes-binder" % "1.3.0" 但它在我的项目中不起作用,因为我在集成后遇到编译错误,所以我暂时隐藏了这种方法。

【问题讨论】:

  • 在读取值时进行正则表达式验证,而不是在路由上
  • 所以答案是在 2.7.x 或 2.7.x 中不可能使用正则表达式在路由中验证可选参数?
  • 我不知道这是否可能(编程中一切皆有可能),但这绝对不是最好的方法

标签: scala playframework play-framework-2.7


【解决方案1】:

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

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)}"
    }
  }
}

现在,如果您更改路由配置,使 birthDateOption[BirthDate] 类型的参数,您将获得所需的行为。

如果您坚持使用正则表达式,您可以使用基于正则表达式的解析器来代替日期格式化程序,并让 BirthDate 包装 String 而不是 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}"
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2020-10-10
    • 2019-01-01
    相关资源
    最近更新 更多