title: Play 2.4 parameterized algebraic data types JSON validation
body: <p>Is it possible to do something like that in Scala / Play 2.4:</p>
  
  <pre class="lang-scala prettyprint-override"><code>sealed trait Location { val `type`: String }
  case class CityLocation(zip_code: String, override val `type`: String = "city") extends Location
  case class AddressLocation(
    society: Option[String],
    first_name: String,
    last_name: String,
    ...
    override val `type`: String = "address"
  ) extends Location
  
  sealed trait Point[T &lt;: Location] { val `type`: String; val location: T }
  case class ShippingPoint[T](override val location: T, override val `type`: String = "shipping") extends Point[T]
  case class PickupPoint[T](override val location: T, override val `type`: String = "pickup") extends Point[T]
  
  object CityLocation {
    implicit val format = Json.format[CityLocation]
  }
  object AddressLocation {
    implicit val format = Json.format[AddressLocation]
  }
  object ShippingPoint {
    implicit def write[T] = Json.writes[ShippingPoint[T]]
    implicit def read[T]: Reads[ShippingPoint[T]] = (
      (__ \ "location").read[T] and
        (__ \ "type").read[String](exactWordRead("shipping", "error.route.shipping.type"))
    )(ShippingPoint[T].apply _)
  }
  object PickupPoint {
    implicit def write[T] = Json.writes[ShippingPoint[T]]
    implicit def read[T]: Reads[PickupPoint[T]] = (
      (__ \ "location").read[T] and
        (__ \ "type").read[String](exactWordRead("pickup", "error.route.pickup.type"))
    )(PickupPoint[T].apply _)
  }
  </code></pre>
  
  <p>??</p>
  
  <p>For now, It does not compile.</p>
  
  <p>The <code>exactWordRead</code> method is defined as follow : </p>
  
  <pre class="lang-scala prettyprint-override"><code>def exactWordRead(word: String, errorMessage: String): Reads[String] = Reads.constraints.pattern(s"^$word${"$"}".r, errorMessage)
  </code></pre>
  
  <hr>
  
  <p><strong>Edit</strong>:</p>
  
  <p>It seems that I maid a step forward thanks to this answer <a href="https://stackoverflow.com/a/29834113/2431728">https://stackoverflow.com/a/29834113/2431728</a> :</p>
  
  <pre class="lang-scala prettyprint-override"><code>sealed trait Location { val `type`: String }
  case class CityLocation(zip_code: String, override val `type`: String = "city") extends Location
  case class AddressLocation(
    society: Option[String],
    first_name: String,
    last_name: String,
    ...
    override val `type`: String = "address"
  ) extends Location
  
  sealed trait Point[T &lt;: Location] { val location: T; val `type`: String }
  case class ShippingPoint[T](override val location: T, override val `type`: String = "shipping") extends Point[T]
  case class PickupPoint[T](override val location: T, override val `type`: String = "pickup") extends Point[T]
  
  object CityLocation {
    implicit val format = Json.format[CityLocation]
  }
  object AddressLocation {
    implicit val format = Json.format[AddressLocation]
  }
  object ShippingPoint {
    implicit def format[T: Format]: Format[ShippingPoint[T]] = (
      (__ \ "location").format[T] and
        (__ \ "type").format[String](exactWordRead("shipping", "error.route.shipping.type"))
    )(ShippingPoint.apply, unlift(ShippingPoint.unapply))
  }
  object PickupPoint {
    implicit def format[T: Format]: Format[PickupPoint[T]] = (
      (__ \ "location").format[T] and
        (__ \ "type").format[String](exactWordRead("pickup", "error.route.pickup.type"))
    )(PickupPoint.apply, unlift(PickupPoint.unapply))
  }
  </code></pre>
  
  <p>However, I doesn't compile yet. The compile error is :</p>
  
  <pre class="lang-scala prettyprint-override"><code>[error] type arguments [T] do not conform to trait Point's type parameter bounds [T &lt;: services.coliswebApi.data.Location]
  [error] case class ShippingPoint[T](override val location: T, override val `type`: String = "shipping") extends Point[T]
  [error]                                                                                                         ^
  [error] type arguments [T] do not conform to trait Point's type parameter bounds [T &lt;: services.coliswebApi.data.Location]
  [error] case class PickupPoint[T](override val location: T, override val `type`: String = "pickup") extends Point[T]
  </code></pre>