Scala Akka HTTP 访问包含在 Option[String] 中的 post 请求参数时出现问题

问题描述 投票:0回答:1

我正在尝试使用 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”
       }
  }
}

scala akka akka-http spray-json
1个回答
0
投票

根据您在上一篇文章中提出的问题,您遇到的问题似乎与akkaakka-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的基础知识。

© www.soinside.com 2019 - 2024. All rights reserved.