播放框架:将结果转换为 Json
Play Framework: Transform Result to Json
如何在可重复使用的操作中将结果转换为 Json?
示例:
object JsonAction {
def apply(block: Request[JsValue] => ???): Action[JsValue] = {
Action(BodyParsers.parse.json) { request =>
val result = block(request)
val finalResult = result.copy(body = Json.toJson(result.body))
finalResult
}
}
}
在我的控制器中:
def index = JsonAction { req =>
Ok(new SomeModel(...))
}
我们的想法是能够将结果模型和表示分离为 json(或 xml,例如)。
我找不到很好的解决方案...
是这样的吗?
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))
}
}
}
和最后的尝试 - 这里我们使用 json.Writes
实例隐式提供 http.Writeable
的实例,并在该实例中将值转换为 JSON,因此我们可以使用 Result
临时工。如果类型有自己的 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))
}
}
}
如何在可重复使用的操作中将结果转换为 Json?
示例:
object JsonAction {
def apply(block: Request[JsValue] => ???): Action[JsValue] = {
Action(BodyParsers.parse.json) { request =>
val result = block(request)
val finalResult = result.copy(body = Json.toJson(result.body))
finalResult
}
}
}
在我的控制器中:
def index = JsonAction { req =>
Ok(new SomeModel(...))
}
我们的想法是能够将结果模型和表示分离为 json(或 xml,例如)。
我找不到很好的解决方案...
是这样的吗?
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))
}
}
}
和最后的尝试 - 这里我们使用 json.Writes
实例隐式提供 http.Writeable
的实例,并在该实例中将值转换为 JSON,因此我们可以使用 Result
临时工。如果类型有自己的 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))
}
}
}