【问题标题】:Scala/Play Framework: Getting Payload from a POST request / NoSuchElementExceptionScala/Play 框架:从 POST 请求/NoSuchElementException 获取有效负载
【发布时间】:2014-06-20 23:04:45
【问题描述】:

我尝试从 Play 2.3 中的 POST 获取有效负载。

所以我用这个表达方式。

val name = request.body.asFormUrlEncoded.get("name").flatMap(_.headOption)

但是当“名称”字段不存在时,我遇到了麻烦。使用调试器,我可以看到 request.body.asFormUrlEncoded 的类型是 Some(Map) 还是 ListMap?我不确定,在调试器中会显示这两个术语。当字段“name”存在时,一切正常,但如果字段“name”缺失,则会抛出 NoSuchElementException。

我可以看到只有调用 request.body.asFormUrlEncoded.get("name") 会返回一个 ArrayBuffer。但是如果“名称”字段不存在,它不应该返回 Some(ArrayBuffer) 和 None 吗?

那么如果字段丢失,我该怎么做才能查询字段的值而不产生异常。

添加: 这是 AnyContentAsFormUrlEncoded 的声明。所以它是一个地图。但是 get on a Map 应该返回 Some 或 None,而不是直接返回对象。

case class AnyContentAsFormUrlEncoded(data: Map[String, Seq[String]]) extends AnyContent

【问题讨论】:

  • 为什么不能为该异常设置一个处理程序?知道该字段是否确实存在并让您的程序在它不存在时处理这种情况是一件好事。
  • 不是这样的。当然我可以把它放在一个 try catch 块中。但并非只有次优解决方案例外。 - 我在 REPL 中玩过,如果我在那里有一个 Map 并在上面调用 get("xxx") 并且地图中没有 xxx,它会返回一个 None。否则我会得到一些(任何东西)。那么问题来了,为什么 FormUrlEncoded 的 Map 上的“get”没有返回 Option?在 Map 或 ListMap 上“get”的 scala 文档中,它说“get”返回一个选项。

标签: scala map playframework nosuchelementexception


【解决方案1】:

您在此处遇到了 Scala 限制:

.get 函数的调用是在您的Option[Map[String, Seq[String]] 上完成的,然后您使用("name"),它被转换为.apply("name")。您实际上是在调用 Map 对象的 apply,如果键不在您的地图中,该对象可能会引发异常。

为避免这种情况,您可以使用:

val name: Option[String] = request.body.asFormUrlEncoded.flatMap(m => m.get("name").flatMap(_.headOption))

【讨论】:

  • 使用 double get get.get("name") 做同样的事情。如果你刚接触 scala,这真的很棘手。我认为双 flatMap 更稳定,但在我的情况下,第一次获取不会失败。什么是更高效的方式。使用 get.get 还是使用 flatMap(get)?
  • 我认为最好从一开始就安全,所以我会选择 flatMap 除非你希望你的应用程序在你的 body 不是 UrlEncoded 时抛出异常
猜你喜欢
  • 2013-01-09
  • 2019-03-13
  • 2021-02-28
  • 1970-01-01
  • 2013-09-23
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多