2015-04-22 99 views
1

如何將結果轉換爲Json的可重用操作?Play Framework:將結果轉換爲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例如)。

我找不到一個很好的解決方案...

回答

4

是這樣的嗎?

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)) 
    } 
    } 
} 
+0

非常感謝您的回答。不幸的是,對我來說重要的一點是能夠使用Ok(new SomeModel(...)),所以我可以在控制器動作中指定非常易讀的狀態代碼。 –

+1

@TimJoseph更新 – Odomontois

+0

再次感謝!現在看起來更像是我想達到的目標。似乎沒有辦法使用「OK(new SomeModel(...))」,然後在JsonAction中調用類似「val result = block(request); Json.toJson(result.getModel)」? –