Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play Scala Read/Write depending on type

i have trouble dealing with Json reader in play framework 2.3 depending on a class field :

My model :

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]
)

My problem is : How can i read MyObject class and keep all values from Json like :

{
  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"
      }
    ]
}

I tried this :

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

But it doesn't work

Many thanks for your help !

MC

like image 859
godo57 Avatar asked Oct 31 '22 13:10

godo57


1 Answers

You can use the orElse method in the Reads trait:

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]

Note that I needed to map the Reads[Price] and Reads[Weight] to Reads[Data] before using orElse because Reads is not covariant (a Reads[Price] is not a Reads[Data]). I also added the verifying reads to check the type value if both Price and Weight happened to have the same structure.

like image 96
Dimitri Avatar answered Nov 15 '22 07:11

Dimitri