Playframework 2.0.X scala - 如何为对象实现多个json读/写?

时间:2013-01-18 09:00:57

标签: json scala playframework-2.0

我们假设有一个json对象Test。 它有两种格式:

{
    "name": "Test",
    "id": "41"
}

{
    "object": {
        "name": "Test",
        "id": "41"
    }
}

我创建了Test.scala:

case class Test (name: String, id: String)

object Test {

    implicit object FopReads extends Format[Test] {

        def reads(json: JsValue): Test = {
            Test (
                (json \ "name").as[String],
                (json \ "id").as[String]
            )
        }

        def writes(ts: Test) = JsObject(Seq(
            "name" -> JsString(ts.name),
            "id" -> JsString(ts.id)
        ))

    }
}

正如您所看到的,实际上,我只处理第一种格式。我的问题是:如何轻松实现它可以以两种格式读写的Format[Test]?我知道json机制在play 2.10中发生了变化。我应该改变这个版本来做我想要的吗?

感谢您的时间!

1 个答案:

答案 0 :(得分:1)

在我看来,你的方法并不理想,你必须重新考虑你的设计。让我解释一下原因。

虽然您可以有效地开发能够读取两种格式的Format[A],但您无法编写可以编写两种格式的Format[A]

trait Format[T]{
    def reads (json: JsValue): T
    def writes (o: T): JsValue
}

如您所见,write方法只有一个参数,因此您的Format[Test]将无法知道它是否应该使用一种或另一种输出格式。如果您遵循推理,您会同意将Format特征委托给特定 Json格式进行写入和读取,而不是在格式之间进行选择。选择正确格式的逻辑与读写正确的格式无关,你应该将它解耦。

说,您可以通过以下方式重新使用格式[测试]:

case class ObjectParser(nestedFormatter:Format[T]) extends Format[T]{
    def reads (json: JsValue): T = nestedFormatter.read(json \ "object")
    def writes (o: T): JsValue  = JsObject("object" -> nestedFormatter.write(o))
}

此类将使用任何现有格式化程序,并使其能够在另一个“对象”节点内进行读写。

想象一下,现在你有一个控制器需要根据url端点生成或解析两个不同的答案:

object TestController extends Controller {

    def endPoint1Action = Action{
        implicit request => 
        generateResponse(FopReads)
    }

    def endPoin21Action = Action{
        implicit request => 
        generateResponse(ObjectParser(FopReads))
    }

    def generateResponse(formatter:Format[Test])(implicit request:Request[AnyContent]):Response  = BadRequest("!")

}