是這樣的嗎?
import play.api.libs.json._
import play.api.mvc._
object JsonAction extends Results {
def apply[A, B](block: A => B)(implicit reads: Reads[A], writes: Writes[B]): Action[JsValue] =
Action(BodyParsers.parse.json) { request =>
val result = for {
a <- Json.fromJson(request.body).asOpt
b = block(a)
} yield Ok(Json.toJson(b))
result getOrElse InternalServerError(???)
}
}
,或者你想在你的塊
object JsonAction extends Results {
def apply[A, B](block: A => (Option[(Status, B)]),
noneStatus: Result = BadRequest("could not parse json"))
(implicit reads: Reads[A], writes: Writes[B]): Action[JsValue] =
Action(BodyParsers.parse.json) { request =>
val result = for {
a <- Json.fromJson(request.body).asOpt
(status, b) <- block(a)
} yield status(Json.toJson(b))
result getOrElse noneStatus
}
}
object MathController {
import JsonAction._
def squareEquasion = JsonAction[Map[String, Double], Set[Double]] { map =>
for {a <- map get "a"
b <- map get "b"
c <- map get "c"
d = b * b - 4 * a * c} yield d match {
case d if d < 0 => (InternalServerError, Set.empty[Double])
case d if d == 0 => (Ok, Set(-b/2 * a))
case d if d > 0 => (Ok, Set(1, -1) map (q => (-b + q * math.sqrt(d))/2 * a))
}
}
}
和最後一次嘗試手動定義產生的狀態 - 我們在這裏的http.Writeable
隱含使用json.Writes
實例提供實例和轉換價值爲JSON這個例子裏面,所以我們可以使用Result
構建器ad-hock。其實,這可能會導致一些不確定性,如果類型有它自己的Writeable
實例(例如String
):
import play.api.http.Writeable
import play.api.libs.json._
import play.api.mvc._
import scala.language.implicitConversions
object JsonAction {
private object Res extends Results
implicit def jsonWriteable[T](implicit writes: Writes[T]): Writeable[T] = {
val jsonWriteable = implicitly[Writeable[JsValue]]
def transform(obj: T) = jsonWriteable.transform(Json.toJson(obj))
new Writeable[T](transform, jsonWriteable.contentType)
}
def apply[A, B](block: A => Option[Result], noneStatus: Result = Res.BadRequest("could not parse json"))
(implicit reads: Reads[A], writes: Writes[B]): Action[JsValue] =
Action(BodyParsers.parse.json) { request =>
val result = for {
a <- Json.fromJson(request.body).asOpt
result <- block(a)
} yield result
result getOrElse noneStatus
}
}
object MathController extends Results{
import JsonAction._
def squareEquasion = JsonAction[Map[String, Double], Set[Double]] { map =>
for {a <- map get "a"
b <- map get "b"
c <- map get "c"
d = b * b - 4 * a * c} yield d match {
case d if d < 0 => InternalServerError("No answer")
case d if d == 0 => Ok(Set(-b/2 * a))
case d if d > 0 => Ok(Set(1, -1) map (q => (-b + q * math.sqrt(d))/2 * a))
}
}
}
非常感謝您的回答。不幸的是,對我來說重要的一點是能夠使用Ok(new SomeModel(...)),所以我可以在控制器動作中指定非常易讀的狀態代碼。 –
@TimJoseph更新 – Odomontois
再次感謝!現在看起來更像是我想達到的目標。似乎沒有辦法使用「OK(new SomeModel(...))」,然後在JsonAction中調用類似「val result = block(request); Json.toJson(result.getModel)」? –