2

使用喷雾路由,我想要一个指令,将查询字符串参数与 JSON 实体合并,两者都是可选的。我希望在任何编组发生之前发生这种情况。

像这样的东西:

val myRoute = mergedParametersAndEntity(as[DomainSpecificClass]) { myobj =>
  // ... code code code ...
  complete(OK, myobj.someMethod)
}

基本上我希望的是以下行为:

当有人提出如下请求时:

POST /v1/resource?a=helloQS&b=helloQS
Content-Type: application/json

{"a":"helloFromJson","c":"helloFromJson"}

那么上面的对象 ( myobj) 可以包含键:

a -> helloFromJson
b -> helloQS
c -> helloFromJson

换句话说,请求正文中指定的项目将覆盖查询字符串中的内容。我知道这一定是可能的,但我根本不知道该怎么做。任何人都可以帮忙吗?

谢谢!

4

2 回答 2

2

我的建议:不要采取这种方法。感觉很脏 如果可以的话,回到绘图板。

考虑到这一点,您将无法使用 Spray 中现有的 JSON 编组支持插入您想要的合并。你需要自己把它缝合起来。这样的事情至少应该为您指明正确的方向(前提是您必须走的方向):

import org.json4s.JsonAST._
import org.json4s.JsonDSL._
def mergedParametersAndEntity[T](implicit m:Manifest[T]): Directive1[T] = {
  entity(as[JObject]).flatMap { jObject =>
    parameterMap flatMap { params =>
      val left = JObject(params.mapValues { v => JString(v) }.toSeq : _*)
      provide(left.merge(jObject).extract[T])
    }
  }
}
于 2014-02-17T10:22:14.620 回答
0

如果有人仍然想知道如何做到这一点,这里有一个小的 Spray 指令,它允许在解组之前将参数值复制到 JSON。它使用 JSON 镜头 ( https://github.com/jrudolph/json-lenses ) 在解组之前修改请求正文。

def updateJson(update: Update): Directive0 = {
  mapRequest((request: HttpRequest) => {
    request.entity match {
      case Empty => request
      case NonEmpty(contentType, data) =>
        try {
          request.copy(entity = HttpEntity(`application/json`, JsonParser(data.asString).update(update).toString))
        }
        catch {
          case e: ParsingException => request
        }
    }
  })
}

这就是你如何使用它。假设您想使用 PUT 请求更新资源并将 ID 从 URL 传递给解组器(顺便说一句,这是一个非常常见的场景):

// Model
case class Thing(id: Long, title: String, description: String, createdAt: DateTime)

// Actor message for the update operation
case class UpdateThing(id: Long, title: String)

// Spray routing
def thingsRoute = 
  path("things" / Segment) { id =>
    put {
      updateJson(field("id") ! set[Long](id)) {
        entity(as[UpdateThing]) { updateThing =>
          complete {
            // updateThing now has the ID set
            (someActor ? updateThing).mapTo[Thing]
          }
        }
      }
    }
  }

您还可以将它与parameters指令结合使用来设置任意 GET 参数。

于 2015-12-06T05:57:59.433 回答