我们假设有一个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中发生了变化。我应该改变这个版本来做我想要的吗?
感谢您的时间!
答案 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("!")
}