automatic sealed trait discriminator takes precedence over apply/unapply methods
tnielens opened this issue · 0 comments
tnielens commented
There seems to be incompatible change between versions 2.4.x and 2.6.14 regarding the sealed types Format
instance macro.
Play JSON Version
2.4.x -> 2.6.14
API (Scala / Java / Neither / Both)
Scala
Expected Behavior
Using the older version of play-json, I have defined a Format
instance of my sealed trait TableColumn
type. See snippet bellow. I use the macro which requires apply
and unapply
methods to be defined on the trait. The macros uses these methods for the serialization and the discriminator field name. The discriminator logic is implemented manually.
As I upgrade to later versions of play-json, I expect the same behavior.
Actual Behavior
The new sealed trait discriminator feature takes precedence over my manual implementation.
Reproducible Test Case
sealed trait TableColumn[T] {
val name: String
val values: List[T]
}
case class DoubleTableColumn(name: String, values: List[Double]) extends TableColumn[Double]
case class StringTableColumn(name: String, values: List[String]) extends TableColumn[String]
// companion object of trait is needed, since apply() and unapply() functions are required on TableColumn
object TableColumn {
def unapply(tableColumn: TableColumn[_]): Option[(String, JsValue)] = {
val (prod: Product, jsValue) = tableColumn match {
case column: DoubleTableColumn => (column, Json.toJson(column)(doubleTableColumnFormat))
case column: StringTableColumn => (column, Json.toJson(column)(stringTableColumnFormat))
}
Some(prod.productPrefix -> jsValue)
}
def apply(className: String, data: JsValue): TableColumn[_] = {
(className match {
case "DoubleTableColumn" => Json.fromJson[DoubleTableColumn](data)(doubleTableColumnFormat)
case "StringTableColumn" => Json.fromJson[StringTableColumn](data)(stringTableColumnFormat)
case _ => throw new IllegalArgumentException(s"className '$className' not recognized.")
}).get
}
implicit lazy val doubleTableColumnFormat: Format[DoubleTableColumn] = Json.format[DoubleTableColumn]
implicit lazy val stringTableColumnFormat: Format[StringTableColumn] = Json.format[StringTableColumn]
// this instance uses the default discriminator field "_type" instead of the apply/unapply methods logic
implicit lazy val tableColumnFormat: Format[TableColumn[_]] = Json.format[TableColumn[_]]
}