I am trying to migrate to the latest version of upickle 0.7.1. Where I had previously passed around implicit Readers and Writers I believe I must now use a single ReadWriter and explicitly define them in a companion object for any case classes I want to serialize. But I cannot figure out how this works for a parameterized type. So for example say I had the following before upgrading (from 0.4.4):
trait OldTrait[T] {
implicit val evr: Reader[T]
implicit val evw: Writer[T]
def save(t: T): String = write(t)
def restore(str: String): T = read[T](str)
}
class MyOldClass[T](implicit val evr: Reader[T], val evw: Writer[T]) extends OldTrait[T] {
}
case class Request[T](msg: T)
val c1 = new MyOldClass[Request[Int]]
The above code compiled fine for me. To migrate this code I have tried the following:
trait NewTrait[T] {
implicit val evrw: ReadWriter[T]
}
class MyNewClass[T](implicit val evrw: ReadWriter[T]) extends NewTrait[T] {
}
object Request {
implicit val rw: ReadWriter[Request[_]] = macroRW
}
val c2 = new MyNewClass[Request[Int]]
But this will not compile for me. I get the following errors:
Don't know how to derive type ...Request[] implicit val rw: ReadWriter[Request[]] = macroRW
... could not find implicit value for parameter evrw: upickle.default.ReadWriter[Request[Int]]
...not enough arguments for constructor MyNewClass: (implicit evrw: upickle.default.ReadWriter[Request[Int]])MyNewClass[Request[Int]]. Unspecified value parameter evrw. val c2 = new MyNewClass[Request[Int]]
What would be the correct approach to migrating the old code?
Not tested, but I would expect you need
implicit def rw[T: ReadWriter]: ReadWriter[Request[T]] = macroRW
So e.g. because there is a ReadWriter[Int]
, there's also a ReadWriter[Request[Int]]
.
(I would be very surprised if this doesn't work, but you can certainly do it manually instead of macroRW
in this case.)