5

当所有输入都有效时,我可以处理这个 json,即使用有效的键(包括大小写)和值。下一步是验证键并在键或值无效时返回 400(错误请求)。添加此验证的好方法是什么?

API 调用

POST http://localhost:8080/api/v1/adsession
Content-Type: application/json
body {
  "sessionId": "abcd123123123",
  "serviceGroup": "1234",
  "targetCode": {"zipcodes":"30096,30188","code2":"value2"}
}

路由处理程序

class AdSessionRoutes(services: Services)(implicit ec: ExecutionContext, log: LoggingContext) extends ApiRoute(services) {

  implicit val timeout = Timeout(10 seconds)

  val postSession = pathPrefix("adsession") & pathEnd & post

  val route: Route = {
    withService("adSession") { service =>

      postSession {
        entity(as[AdSession]) { adSession =>
          log.info(s"Processing POST ${adSession}")
          val future = (service ? CreateAdSession(adSession)).mapTo[AdSession]

          onComplete(future) {
            case Success(result) =>
              complete(StatusCodes.Created, result)

            case Failure(e) =>
              log.error(s"Error: ${e.toString}")
              complete(StatusCodes.InternalServerError, Message(ApiMessages.UnknownException))
          }
        }
      }
    }
  }
}

模型对象

case class AdSession(
  sessionId: String,
  serviceGroup: String,
  targetCodes: Map[String,String],
  id: Option[String] = None)

object AdSessionJsonProtocol extends DefaultJsonProtocol {
  implicit val adSessionFormat = jsonFormat4(AdSession)
}

entity(as[AdSession]) 确实将键映射到案例类字段,但我不确定如何捕获这些错误。我想捕获这些错误并添加额外的验证并返回 400 和有效的 json 错误响应。

4

2 回答 2

3

我知道这可能有点晚了,但是从 akka-http-2.4.6 开始,您可以将验证逻辑放在案例类中。查看此以获取有关如何执行此操作的信息。

于 2016-05-28T09:50:41.967 回答
2

像这样定义你自己的readwrite方法AdSession

object AdSessionJsonProtocol {
    implicit object adSessionJsonFormat extends RootJsonFormat[AdSession] {
        override def read(json: JsValue): AdSession = ???
        override def write(obj: AdSession): JsValue = ???
    }
}

read函数内部,您可以执行额外的验证。

另一个问题是如何将收集到的错误传递给 Spray 路由。我想建议你AdSession换成Either[String, AdSession],例如:

postSession {
        entity(as[Either[String, AdSession]]) { adSession =>

所以,现在你的adSessionJsonFormat遗嘱看起来像:

implicit object adSessionJsonFormat extends RootJsonFormat[Either[String, AdSession]] {

    override def read(json: JsValue): Either[String, AdSession] = {
      // json.asJsObject.fields access fields, perform checks
      // if everything is OK return Right(AdSession(...))
      // otherwise return Lift("Error Message")
    }

    override def write(obj: Either[String, AdSession]): JsValue = ???
}

但是,我认为可以使用一些隐式魔法以更优雅的方式解决它。

于 2015-02-02T10:10:42.083 回答