scala - 从 Map (Play 框架 request.body.asFormUrlEncoded) 转换为 case 类,反之亦然,使用更少的样板文件(与非类型化世界交互)

标签 scala playframework playframework-2.3

这是一个具体的例子,尽管我在更一般的情况下遇到过这个问题。

我正在研究 Play 2.3 Web 应用程序和 Slack 之间的集成通过自定义斜杠命令。 (注意:Slack 有关于自定义斜杠命令 API 格式的文档,但我不相信我可以为未登录的读者直接深层链接它们。)

Slack 将(当用户适当调用时)使用已知格式的标准形式 URL 编码正文 POST 到我的端点。他们的官方示例是:

token=KpADMkoKxZJRGKTG8kJoWXGC
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
user_id=U2147483697
user_name=Steve
command=/weather
text=94070

在我的应用程序中,我使用案例类对该请求进行建模。

case class SlashCommand(
  token: String,
  teamId: String,
  teamDomain: String,
  channelId: String,
  channelName: String,
  userId: String,
  userName: String,
  command: String,
  text: String
)

顺便问一下,除了将每个字段设置为 String 之外,还有其他方法可以更好地实现类型约束吗?

我在从 Play 框架表示形式的 URL 编码转换为案例类时遇到问题。这是我目前拥有的代码,我相信它可以正常工作,但我觉得它过于重复。

object SlashCommand {

  def parseFromMap(in: Map[String, String]): Option[SlashCommand] = {
    for {
      token <- in.get("token")
      teamId <- in.get("team_id")
      teamDomain <- in.get("team_domain")
      channelId <- in.get("channel_id")
      channelName <- in.get("channel_name")
      userId <- in.get("user_id")
      userName <- in.get("user_name")
      command <- in.get("command")
      text <- in.get("text")
    } yield SlashCommand(
      token,
      teamId,
      teamDomain,
      channelId,
      channelName,
      userId,
      userName,
      command,
      text
    )
  }

  def parseFromRequest(req: Request[AnyContent]): Option[SlashCommand] = {
    req.body.asFormUrlEncoded.map { m =>
      m.mapValues(_.last)
    }.flatMap(parseFromMap)
  }

}

我理想中想要排除的有些重复的部分是:

  • 显式 for 与显式 gets
  • 显式构建案例类
  • Request[AnyContent] 手动转换为 Map[String, Option[String]Map[String, String]

是否有任何方法可以减少这些转换中的重复并提高可读性?

此外,我可能很快就需要相反的操作,即从案例类到 Map 和/或表单 URL 编码和/或 JSON 的转换。有什么方法可以减少重复吗?

提前致谢!

编辑:我一直在进一步思考这个问题,我认为我可以使用 Play 框架表单处理来处理前向案例做一些事情。

最佳答案

play Forms API 处理从 RequestMap[String, String]JsValue 到您喜欢的类型的绑定(bind)(使用 Form.bindForm.bindFromRequest),并且有一种声明式的方式来描述约束。所以你的想法编辑对我来说听起来很正确!

Play 文档中有关表单 API 的更多信息: https://www.playframework.com/documentation/2.3.x/ScalaForms

关于scala - 从 Map (Play 框架 request.body.asFormUrlEncoded) 转换为 case 类,反之亦然,使用更少的样板文件(与非类型化世界交互),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29227106/

相关文章:

scala - Play Framework 2.3 中的域路由

scala - play框架中的错误处理

scala - Scala 代码究竟在什么时候执行堆分配?

scala - 如何在 Scala 中重构嵌套的 Option.folds?

scala - Kafka 分区键无法正常工作

java - play框架中用户上传的文件放在哪里?

java - 我如何检索通过java play中的post传递的数据

scala - 编译Build.scala时如何设置SBT使用的scalacOptions?

playframework - Bean是不是增强了?

playframework - Play Framework 2.3 - 不检测变化