【问题标题】:Play Scala Read/Write depending on type根据类型播放 Scala 读/写
【发布时间】:2026-02-03 22:20:09
【问题描述】:

根据类字段,我无法在 play framework 2.3 中处理 Json 阅读器:

我的模特:

trait Data{
  val id:String
  val type:String
  val creation_date:Date
}

case class Price(
  id:String,
  type:String,
  creation_date:Date,
  amount:Int,
  currency:String) extends Data

case class Weight(
  id:String,
  type:String,
  creation_date:Date,
  value:Int,
  unit_of_measurement:String) extends Data

case class MyObject(
  id:String,
  data:List[Data]
)

我的问题是: 我如何读取 MyObject 类并保留 Json 中的所有值,例如:

{
  id:"1",data:
    [
      {
        id:"1",
        type:"price",
        creation_date:"2014-12-01T00:00:00.000Z",
        amount:99,
        currency:"dollar"
      },
      {
        id:"1",
        type:"price",
        creation_date:"2014-12-01T00:00:00.000Z",
        amount:99,
        currency:"dollar"
      },
      {
        id:"1",
        type:"weight",
        creation_date:"2014-12-01T00:00:00.000Z",
        value:2,
        unit_of_measurement:"tonne"
      }
    ]
}

我试过这个:

implicit val myObjectReads: Reads[MyObject] = (
  ....
  (__ \ "data").read(Reads.traversableReads[List,Data])

但它不起作用

非常感谢您的帮助!

MC

【问题讨论】:

标签: json scala playframework


【解决方案1】:

你可以在Reads trait 中使用orElse 方法:

import play.api.libs.json.Reads.verifying

val priceReads: Reads[Price] = verifying[Price](_.`type` == "price")(Json.reads[Price])
val weightReads: Reads[Weight] = verifying[Weight](_.`type` == "weight")(Json.reads[Weight])
implicit val dataReads: Reads[Data] = priceReads.map(identity[Data]) orElse weightReads.map(identity[Data])
implicit val myObjectReads: Reads[MyObject] = Json.reads[MyObject]

请注意,在使用orElse 之前,我需要将Reads[Price]Reads[Weight] 映射到Reads[Data],因为Reads 不是协变的(Reads[Price] 不是Reads[Data])。如果PriceWeight 恰好具有相同的结构,我还添加了verifying 读取以检查类型值。

【讨论】: