有没有一种简单的方法(一个衬里)可以将额外的属性添加到 json 输出而无需编写我自己的 Json.writes

Is there a simple way (one liner) to add an extra properties to the json output without having to write my own Json.writes

import play.api.libs.json.JsonConfiguration.Aux
import play.api.libs.json._

case class EmailStats(id: Int, providerId: String, stats: Option[String])

case class Email(id: Int = 0, createdAt: Option[String], updatedAt: Option[String]) {

  implicit val config: Aux[Json.MacroOptions] = JsonConfiguration(SnakeCase)
  implicit def format: OFormat[Email] = Json.using[Json.WithDefaultValues].format[Email]
  implicit val writes: OWrites[Email] = Json.writes[Email]
  implicit val reads:  Reads[Email]   = Json.reads[Email]

  private var emailStats: Seq[EmailStats] = Seq[EmailStats]()

  def getEmailStats(): Seq[EmailStats] = emailStats
}

输出序列化:

{"id": 0, "created_at": "01/08/2020 00:00:12","created_at": "01/09/2020 01:56:05"}

有没有办法向写入添加额外的 属性 或方法,以便呈现额外的 JSON?

{"id": 0, "created_at": "01/08/2020 00:00:12","created_at": "01/09/2020 01:56:05", "email_stats": [...]}

我不想做以下事情:

implicit val writes: Writes[Email] = (email: Email) => Json.obj(
  "id" -> email.id,
  "created_at" -> email.createdAt,
  "updated_at" -> email.updatedAt
  "email_stats" -> email.getEmailStats.map(stat=>Json.toJson(stat))
)

谢谢。

如果您可以调整 Case 类:

,这是一个解决方案
import play.api.libs.json._

  case class EmailStats(id: Int, providerId: String, stats: Option[String] = None)
  object EmailStats {
    implicit def format: OFormat[EmailStats] = Json.using[Json.WithDefaultValues].format[EmailStats]

  }
  case class Email(id: Int = 0, createdAt: Option[String], updatedAt: Option[String], emailStats: Seq[EmailStats]) {
  }
  object Email {
    implicit def format: OFormat[Email] = Json.using[Json.WithDefaultValues].format[Email]

  }
  1. 调整构造函数(添加emailStats)。

  2. 伴随对象中添加格式化程序。

这里是例子:

val jsonStr = """{"id": 0, "createdAt": "01/08/2020 00:00:12","updatedAt": "01/09/2020 01:56:05", "emailStats": [{"id": 3, "providerId": "provider" }]}
              |""".stripMargin

Json.parse(jsonStr).validate[Email] // -> JsSuccess(Email(0,Some(01/08/2020 00:00:12),Some(01/09/2020 01:56:05),List(EmailStats(3,provider,None))),)

如果您需要更多解释,请告诉我。

请注意,我将一些属性更改为 CamelCase,以简化示例。

implicit val emailFormat: OFormat[Email] = {
  val f = Json.using[Json.WithDefaultValues].format[Email]

  OFormat(f, email => {
    f.writes(email) + ("email_stats" -> Json.toJson(email.getEmailStats))
  }
}

顺便说一句,通常将隐式添加到伴随对象而不是案例 class 本身。