使用 Writes trait with unapply 仅序列化特定属性

Serialize only specific attributes using Writes trait with unapply

假设我有这样一个案例 class:

case class Product(ean: Long, name: String, description: String)

我想将这个 class 的对象序列化为 Json,我可以像这样实现 Writes 特性:

implicit val productWrites: Writes[Product] = (
  (JsPath \ "ean").write[Long] and
  (JsPath \ "name").write[String] and
  (JsPath \ "description").write[String]
)(unlift(Product.unapply))

如果我想序列化对象的所有属性,这很好用。现在假设我不想序列化 ean。我试过这样的事情:

implicit val productWrites: Writes[Product] = (
  (JsPath \ "name").write[String] and
  (JsPath \ "description").write[String]
)(unlift(Product.unapply))

这似乎行不通,因为需要使用所有 fields/attributes unapply 方法 returns。

有没有办法让第二种序列化方法只适用于我想要序列化的属性,或者我必须使用这样的方法:

implicit object ProductWrites extends Writes[Product] {
  def writes(p: Product) = Json.obj(
    "name" -> Json.toJson(p.name),
    "description" -> Json.toJson(p.description)
  )
}

这是唯一的方法吗?

我认为你的最后一个例子是可行的。这是使用隐式 val 而不是隐式对象做同样事情的另一种方法:

implicit val productWrites: Writes[Product] = Writes { p =>
  Json.obj(
    "name" -> Json.toJson(p.name),
    "description" -> Json.toJson(p.description)
  )
}

unlift(Product.unapply) 具有类型 Product => (Long, String, String)

在这种情况下,参数的类型应为 Product => (String, String)。你可以像下面这样写一个函数文字。

implicit val productWrites: Writes[Product] = (
  (JsPath \ "name").write[String] and
  (JsPath \ "description").write[String]
)(p => (p.name, p.description))