0
votes

Imagine the following scenario:

I have two classes, which one extends the other. I want to define implicit reads to convert from json to classes. Look at the example:

case class A(field1: String, field2: Int)

object A {
  implicit val reads: Reads[A] = (
    (__ \'field1).read[String] and
    (__ \'field2).read[Int]
  )(A.apply _)
}

case class B(field1: String, field2: Int, field3: Boolean)

object B {
  implicit val reads: Reads[B] = (
    (__ \'field1).read[String] and
    (__ \'field2).read[Int] and
    (__ \'field3).read[Boolean]
  )(B.apply _)
}

My issue is how to avoid code duplication in the implicit reads. If class B extends A, how can the Reads[B] reuse Reads[A] and avoid code duplication in the reader? I know that in this case, class B isn't extending A, because they are defined as case classes. I can change their definition to be a normal classes or even define a trait if needed.

I need to keep the relation between classes in the way that B is an A

Thank you.

1

1 Answers

1
votes

You can try smth like:

import play.api.libs.json._
import play.api.libs.functional.syntax._

object A {
  val readsFields = (__ \'field1).read[String] and (__ \'field2).read[Int]
  implicit val reads: Reads[A] = (
    aReadsFields
  )(A.apply _)
}

object B {
  implicit val reads: Reads[B] = (
    A.readsFields and
    (__ \'field3).read[Boolean]
  )(B.apply _)
}

Alternatively you can define relations between classes:

case class A(field1: String, field2: Int)

object A {
  implicit val reads: Reads[A] = (
    (__ \'field1).read[String] and
    (__ \'field2).read[Int]
  )(A.apply _)
}

case class B(field1: A, field3: Boolean)

object B {
  implicit val reads: Reads[B] = (
    (__ \'field1).read[A] and
    (__ \'field3).read[Boolean]
  )(B.apply _)
}

Check play framework tutorial for details: https://www.playframework.com/documentation/2.4.x/ScalaJson