我想支持提交到同一网址的几种不同内容类型:
例如:
application / x-www-form-urlencoded,multipart / form-data,application / json
我想做的事情如下:
post { contentType(`application/x-www-form-urlencoded`) | contentType(`multipart/form-data`) { // user POSTed a form entity(as[MyCaseClass]) { data => complete { data.result } } } ~ contentType(`application/json`) { // user POSTed a JSON object entity(as[MyCaseClass]) { data => complete { data.result } } } }
解决方法
由于喷雾编组系统具有很强的巧妙性,因此有一种非常优雅的方式可以实现这一目标.代码(
gist)说明了这一点:
case class User(name: String,no: Int) // Json marshaller object UnMarshalling extends DefaultJsonProtocol { val jsonUser = jsonFormat2(User) val textUser = Unmarshaller[User](`text/plain`) { case httpentity.NonEmpty(contentType,data) => val res = data.asstring.drop(5).dropRight(1).split(',') User(res(0),res(1).toInt) } implicit val userMarshal = Unmarshaller.oneOf(jsonUser,textUser) } class UnMarshalTest extends FunSpec with ScalatestRouteTest with Matchers { import UnMarshalling._ // Marshals response according to the Accept header media type val putOrder = path("user") { put { // Namespace clash with ScalaTestRoutes.entity MarshallingDirectives.entity(as[User]) { user => complete(s"no=${user.no}") } } } describe("Our route should") { val json = """ {"name" : "bender","no" : 1234} """ it("submit a json") { Put("/user",httpentity(`application/json`,json)) ~> putOrder ~> check { responseAs[String] should equal("no=1234") } } it("Submit text") { Put("/user",httpentity(`text/plain`,"""User(Zoidberg,322)""")) ~> putOrder ~> check { responseAs[String] should equal("no=322") } } } }