【问题标题】:How to provide a custom Deserializer for akka-http query parameters?如何为 akka-http 查询参数提供自定义反序列化器?
【发布时间】:2016-07-13 23:46:02
【问题描述】:

akka-http 2.4.7 reference 声明可以自定义Deserializers 来转换查询参数,而无需将它们存储在中间变量中:

"amount".as[Int] 将参数“amount”的值提取为 Int,您需要在范围内匹配的反序列化器才能工作(另请参阅 Unmarshalling)

"amount".as(deserializer) 使用显式反序列化器提取参数“amount”的值

但是,该页面上的 Deserialized parameter 示例并未显示自定义反序列化程序的使用方式。

我如何定义一个,以便我可以说,例如.as[MyType]?

我认为文档有问题,因为我在 akka 来源的任何地方都找不到Deserializersearch

在 Akka 文档中如何排版 Deserializer 的屏幕截图。

【问题讨论】:

    标签: akka-http


    【解决方案1】:

    Deserializer 只是 akka-http 2.4.7Unmarshaller 的名称(akka-http 2.4.8 相同)

    编辑:假设您要提取一个名为 type 的查询参数,并且您想要一个 Deserializer 可以将 type 参数从 String 模式匹配到MyType.

    您的服务器应用程序中的route 可能如下所示:

    object MyServer {
      ...
      // Assuming that you're requiring a
      // `type` parameter from a `POST` request
    
      import MyType._
    
      val route =
        post {
          parameter('type.as(myTypeDeserializer)) { myTypeValue =>
            complete {
              // `myTypeValue` is already pattern-matched
              // to type `MyType` here thanks to `myTypeDeserializer`
              ...
            }
          }
        }
      ...
    }
    

    您的 MyType 对象可能如下所示:

    object MyType {
      case object Type1 extends MyType
      case object Type2 extends MyType
      case object Type3 extends MyType
    
      import akka.http.scaladsl.unmarshalling.Unmarshaller
    
      // Here we pattern match the query parameter,
      // which has type `String`, to a `MyType`
      val stringToMyType = Unmarshaller.strict[String, MyType] {
        case "type1" => MyType.Type1
        case "type2" => MyType.Type2
        case "type3" => MyType.Type3
      }
    }
    

    因此,如果用户请求不受支持的 type 参数,akka-http 将自动抛出 BadRequest 响应。

    【讨论】:

    • 我认为它们可能是相同的。但是如果是这样,为什么Deserializer在代码字体中:doc.akka.io/docs/akka/2.4.7/scala/http/routing-dsl/directives/…它暗示它是一个接口或它自己的一个类。另外,我想转换查询参数 -> 案例类,与您的示例处理的 HttpEntities 无关。
    • 很高兴您展示了Unmarshaller.strict 参数实际上是一个偏函数。可以使用它,它会使我的解决方案(如下)也更简单。
    【解决方案2】:

    我能够根据PredefinedFromStringUnmarshallers.scala 内置示例正确声明自定义查询参数编组器。

    implicit val desId: Unmarshaller[String,Context.Id] = Unmarshaller.strict[String, Context.Id] { s =>
      Context.Id.parseOpt(s).getOrElse(
        if (s=="") throw Unmarshaller.NoContentException
        else throw new IllegalArgumentException( s"Not a valid id: '$s'" )
      )
    }
    

    显式提供返回类型似乎很重要。

    【讨论】:

    • if (s=="") 可以被部分函数条目中的条件替换。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多