我正在尝试使用 Akka HTTP Server 和 Scala 编程语言创建 Post 请求路径。
成功发出并接收 post 请求数据后,我想访问
country
参数内的 device
字段的值。
访问此参数的最佳方式是什么?
我使用 SprayJSON 作为编组器。
当前代码给出错误
Found: Option[Option[String]] Required: String
。
再次,请求已成功处理,我只是不知道如何访问
country
参数内的 device
字段的值。
代码如下。
案例类别:
case class Geo(country: Option[String])
case class Device(id: String, geo: Option[Geo])
case class dataRequest(id: String, device: Option[Device])
Post请求路径:
Path(“submit”) {
Post {
Entity(as[dataRequest]) { data_request_params =>
data_request_params.device.map(dev => dev.geo.map(geo => {
val geoDevice = geo.country
}))
}
}
}
请求正文:
{
“id”: “fghq1I123”,
“device”: {
“id”: “0004a672f”,
“geo”: {
“Country”: “AU”
}
}
}
根据您在上一篇文章中提出的问题,您遇到的问题似乎与akka和akka-http无关。它与 scala 的类型系统有关。
首先你需要了解
Option
类是如何工作的,同时map
和flatMap
有什么区别。
map
方法具有签名Option[A].map[B](A => B): Option[B]
。这意味着,它将把 Option
中包含的值(如果选项是 Some
类型,否则不会执行任何操作)从 A
转换为 B
。例如:// this produces a `Option[Int]`
val optionInt: Option[Int] = Option(1)
// this produces a `Option[String]` because the return type of the function I'm passing as parameter is a `String`
val optionString: Option[String] = optionInt.map(int => int.toString)
// this produces a `Option[Option[Boolean]` because the return type of the function is an `Option[Int]`
// remember that the map method expect a function A => B and returns B
// in the following example B is of type of Option
val optionOptionBoolean: Option[Option[Boolean]] =
optionInt
.map(int =>
optionString
.map(string => int == string)
)
flatMap
方法具有签名 Option[A].flatMap[B](A => Option[B]): Option[B]
。如您所见,预期的函数是 Option[B]
,返回类型是 Option[B]
。这就是针对这一特定案例发挥您所需魔力的工具// a class with an Option field
case class NestedOption(optionInt: Option[Int])
// a class with a field that is an Option of another class that contains an Option field
case class Root(nestedOption: Option[NestedOption])
val nestedOption: Option[NestedOption] = Some(NestedOption(1))
val root: Root = Root(nestedOption)
// to access the nested Option field and transform from Option[Int] to Option[String]
val optionString = root
.flatMap( nestedOption => // I have access to the field `nestedOption` of Root
nestedOption
.optionInt // this field is of type Option, where I can call `map`
.map( int => i.toString) // returning an Option[String] for the `flatMap`
)
// this can also be written much cleaner using for yield
val optionString = for {
nestedOption <- root
int <- nestedOption.nestedOption.optionInt
} yield int.toString
修复代码中的错误
Path(“submit”) {
Post {
Entity(as[dataRequest]) { data_request_params =>
// the code below will return an Option of the value type you return in the last line
// if some of the `Option`s are None, you will get a `None`
val anotherOption = for {
device <- data_request_params.device
geo <- device.geo
country <- geo.country
} yield // the logic you need to apply here
}
}
}
这里有一个很好的链接,可以了解更多信息
Option
同时我建议先学习Scala的基础知识。