【问题标题】:Making a model being able to convert itself to JSON使模型能够将自身转换为 JSON
【发布时间】:2014-01-25 08:33:04
【问题描述】:

我浏览了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。我该怎么做?

附:抱歉,我忘了提到 MyClass 有 java.util.UUID 作为 Id 和其他一些类作为字段:

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

所以Json.writes[MyClass] 至少因为UUID 不起作用。

【问题讨论】:

    标签: json scala playframework playframework-2.2


    【解决方案1】:

    您可以像这样将宏生成的Writes[MyClass] 添加到MyClass 的伴随对象中:

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

    方法toJson 隐式接受Writes[T] 类型的参数。当类型参数TMyClass 时,编译器会尝试查找此类隐式值,并且MyClass 的伴随对象始终在作用域内,因此您不必手动导入myClassWrites

    另见Where does Scala look for implicits?

    Json.writes 需要隐式 Writes 用于所有构造函数参数。

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

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

    对于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]
    }
    

    【讨论】:

    • 没关系,我做到了,但请看看我的更新。
    • 尝试为 UUID 对象提供单独的 Writes 对象。不过,不确定它是否有效
    • 由于MyClass是一个case类,创建对象MyClass不会报错吗?
    • @Alex:为case class 创建一个伴随对象是一种常见的做法。编译器会将applyunapply 方法添加到此伴随对象。
    【解决方案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 中!您可以使用写入/读取的宏生成器。 文档:http://www.playframework.com/documentation/2.2.x/ScalaJsonInception

    implicit val myClassFormat = Json.format[MyClass]
    

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

    更新: 当您使用其他类 UUID 更新答案时,请尝试为 UUID 类提供单独的写入或格式。它不适用于宏,因为它来自 java.util 包,因此您应该提供自定义写入,就像前面提到的那样。

    【讨论】:

      猜你喜欢
      • 2020-10-28
      • 1970-01-01
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多