You have two options:
1. Require all Writes[ClassA]
, Writes[ClassB]
, etc in your function
You might have to define another partial function and have receive
call that since you don't have the signature
2. Use the Writes
instance directly to convert to Json
// companion object of ClassA
object ClassA {
val jsonWrites: Writes[ClassA]
}
And since inside the case matching scope you know it's a ClassA, you can use the Writes[ClassA] instance directly and everything will typecheck.
case obj: ClassA =>
return ClassA.jsonWrites.writes(obj)
EDIT:
A third option that is both less error prone and flexible is to define a list of functions that 1. check whether an obj: Any
is an instance of T
and if so converts it to Json.
Here's a minimal snippet I have working using Scala worksheet. See checkIsInstanceAndConvertToJson
:
import scala.reflect.ClassTag
case class Json(str: String)
trait Writes[A] {
def writes(obj: A): Json
}
// Generate a function that
// 1. Checks whether an object (Any) is an instance of `T`
// 2. Convert it to Json if it is
// The implementation of checking function. All unsafety is encapsulated
def checkIsInstanceAndConvertToJson[T: Writes](implicit t: ClassTag[T]): Any => Option[Json] = (obj: Any) => {
if (t.runtimeClass.isInstance(obj)) {
Some(implicitly[Writes[T]].writes(obj.asInstanceOf[T]))
}
else None
}
// ==========
// USAGE
// ==========
object Foo {
implicit val jsonWrites = new Writes[Foo] {
override def writes(obj: Foo) = Json("Foo")
}
}
class Foo
object Bar {
implicit val jsonWrites: Writes[Bar] = new Writes[Bar] {
override def writes(obj: Bar) = Json("Bar")
}
}
class Bar
// Defining a list of functions that checks whether
// an object is of an instance, and if so, converts it to Json
val checkFuncs = Vector[Any => Option[Json]](
checkIsInstanceAndConvertToJson[Bar],
checkIsInstanceAndConvertToJson[Foo]
)
val t: Any = new Bar
val iter = checkFuncs.iterator
var json: Option[Json] = None
while (json.isEmpty && iter.hasNext) {
val func = iter.next()
json = func(t)
}
println(json)
The above snippets prints Some(Json(Bar))