好的,我会告诉你如何做你想做的事,然后我会告诉你为什么不应该这样做。
如果您想要为您自动生成格式,那么您只需要实现一个隐式宏。我们需要区分我们希望为哪些类型自动生成格式,如果你只是为Any 生成它,那么它将覆盖String 之类的东西,这会很糟糕。因此,我们将定义一个所有案例类都将实现的特征:
trait ImplicitJsonFormat
现在我们为它实现我们的隐式宏:
import play.api.libs.json._
import scala.language.experimental.macros
trait JsonImplicits {
// This works for Play 2.5, in Play 2.6 it becomes JsMacroImpl.implicitConfigFormatImpl
implicit def implicitJsonFormat[A <: ImplicitJsonFormat]: OFormat[A] = macro JsMacroImpl.formatImpl[A]
}
所以现在任何你想要自动生成格式的东西,你只需要扩展ImplicitJsonFormat,并确保任何需要的隐式格式都已经混合了JsonImplicits:
import play.api.libs.json.{Json, OFormat}
case class ResponseModel(content: NestedCaseClassModel)
object ResponseModel extends JsonImplicits {
implicit val format: OFormat[ResponseModel] = Json.format
}
case class NestedCaseClassModel(value: String) extends ImplicitJsonFormat
你有它,NestedCaseClassModel 会自动生成它的格式。当然你也可以自动生成ResponseModel的格式。
但你真的不应该这样做。为什么?有时,明确是有价值的。这些 json 结构不仅仅是无关紧要的偶然事物。它们构成了您的 REST API 的协议,或者您正在使用的任何协议。这通常是您想要明确说明的事情,并且在整个代码库中保持一致。通过明确定义每种伴随类型的格式,您可以在这个一致的地方查找格式是什么。当您需要自定义它时,您可以用手动格式声明替换您的宏,并且您没有更改任何声明格式的方法,答案仍然在于查看伴随对象上的格式字段.
当然,当您预先创建项目时,声明所有这些格式可能有点乏味。但这是一件容易做的事情,容易做对,一旦完成,它就完成了。随着代码库的发展和进步,无论如何,您可能会在伴随对象中包含其他内容,并且您会发现自己需要改进格式,并在迁移代码库和协议架构时远离宏不同的方向。