使模型能够将自身转换为JSON

时间:2014-01-25 08:33:04

标签: json scala playframework playframework-2.2

我在http://www.playframework.com/documentation/2.2.x/ScalaJsonRequests处运行JSON文档,但没找到我需要的内容。我需要的是让我的类能够像这样转换为JSON:

# model
case class MyClass(a: Int, b: String ....)

# controller

def myAction = Action {
  val myClass = getMyClass()
  Ok(toJson(myClass))
}

因此,只要我调用Ok(toJson(myClass)),它就会自动转换为JSON。我怎么能这样做?

P.S。对不起,我忘了提到MyClass java.util.UUID作为Id而其他一些类作为字段:

case class MyClass(id: UUID, a: Int, b: String, c: MyClass2 ....)

所以Json.writes[MyClass]至少因为UUID而无效。

2 个答案:

答案 0 :(得分:5)

您可以将宏生成的Writes[MyClass]添加到MyClass的伴随对象中,如下所示:

object MyClass {
  implicit val myClassWrites = Json.writes[MyClass]
}

方法toJson隐式接受Writes[T]类型的参数。当类型参数MyClassT时,编译器会尝试查找此类隐式值,MyClass的伴随对象始终在范围内,因此您无需手动导入myClassWrites

另见Where does Scala look for implicits?

Json.writes要求所有构造函数参数都隐式Writes

case class MyClass(id: UUID, a: Int, b: String, c: MyClass2)

如果MyClass2是案例类,您应该在其配套对象中使用Writes[MyClass2]创建Json.writes

对于java.util.UUID,您应手动创建Writes,例如:

implicit val uuidWrites: Writes[UUID] = Writes{ uuid => JsString(uuid.toString) }

您可以在某个帮助程序对象中创建uuidWrites,然后在需要时导入,如下所示:

object MyClass {
  import UuidHelper.uuidWrites 
  // note that you don't have to import MyClass2.myClass2Writes here
  implicit val myClassWrites = Json.writes[MyClass]
}

答案 1 :(得分:2)

您需要提供带Writes[MyClass](或Format)描述的隐式val。 Play2.0.x:

import play.api.libs.json._

implicit val myClassWrites = new Writes[MyClass] {
  def writes(c: MyClass): JsValue = {
    Json.obj(
        "a" -> c.a,
        "b" -> c.b,
         ...
    )
  }
}

Play2.1.x +

implicit val myClassWrites = (
  (__ \ "a").write[String] ~
  (__ \ "b").write[Int] ~
  ...
)(unlift(MyClass.unapply))

更多文档: http://www.playframework.com/documentation/2.2.x/ScalaJsonCombinators

但正如senia提到的那样,在Play的新版本中!你可以使用Writes / Reads的宏生成器。 文档:http://www.playframework.com/documentation/2.2.x/ScalaJsonInception

implicit val myClassFormat = Json.format[MyClass]

这将为您提供读取和写入。

<强>更新 当您使用其他类UUID更新答案时,请尝试为UUID类提供单独的写入或格式。它不适用于宏,因为它来自java.util包,所以你应该提供一个自定义的Writes,就像之前提到的那样。