0

Now I wanna serialize/deserialize Json data, and there are several json libraries to choose. However, they use different context-bounds for encoding/decoding, which make it hard to define a trait for them.

trait JsonLib {
  // def writes[T](data: T): String
  // def reads[T](jsonStr: String): Option[T]
}

object JsonCirce extends JsonLib {
  import io.circe.Encoder._
  import io.circe.Decoder._

  def writes[T: Encoder](data: T): String = ...
  def reads[T: Decoder](jsonStr: String): Option[T] =
}

//spray-json
object JsonSpray extends JsonLib {
  import spray.json._

  def writes[T: JsonWriter](data: T): String = ...

  def reads[T: JsonReader](jsonStr: String): Option[T] = ...
}

Is there a way to define the writes/reads in the trait?

Ringo
  • 3
  • 1
  • You want to generically define a trait which accepts multiple encoders/decoders from multiple libraries? If so, mind if I ask why you need multiple serialization libraries? – Yuval Itzchakov Apr 28 '17 at 05:22
  • We have a big Json and the serialization time is important for the web service, so I write a benchmark to test the performance of different libraries. – Ringo Apr 28 '17 at 05:51
  • The service communicates with some other services, so I want a generic trait for all the data types instead of writing JsonLib trait for every data type. – Ringo Apr 28 '17 at 05:58
  • If this is for performance tests, I'd avoid the overhead of using generics and go with plain old method invocation to test each library. Don't mind the duplicate code. – Yuval Itzchakov Apr 28 '17 at 05:58
  • It sound fair. It's an interesting topic to generalize the generic methods though. – Ringo Apr 28 '17 at 06:03
  • Interesting solutions are not always the best solutions. And also are not always worth the complications cause to achieve the "interesting-ness". – sarveshseri Apr 28 '17 at 06:57

1 Answers1

0

You can generalize the type classes using higher kind types like:

import scala.language.higherKinds
import scala.util.Try
import spray.json._
import DefaultJsonProtocol._

trait JsonLib[R[_], W[_]] {
  def writes[T: W](data: T): String

  def reads[T: R](jsonStr: String): Option[T]
}

//spray-json
object JsonSpray extends JsonLib[JsonReader, JsonWriter] {

  override def writes[T: JsonWriter](data: T): String =
    data.toJson.compactPrint

  override def reads[T: JsonReader](jsonStr: String): Option[T] =
    Try(jsonStr.parseJson.convertTo[T]).toOption
}

// Test
JsonSpray.writes(List(1, 2))
JsonSpray.reads[List[Int]]("[1,2]")
PH88
  • 1,796
  • 12
  • 12