1

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

{
    "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 中发生了变化。我应该改变这个版本来做我想做的事吗?

感谢您的时间 !

4

1 回答 1

1

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

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

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

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

话虽如此,您可以通过以下方式重新使用您的 Format[Test] :

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("!")

}
于 2013-01-18T14:15:40.403 回答