Spray JSON Format and Conversion Error - scala

I have a trait for which I wanted to write Typeclasses for. This trait actually is a contract to do JSON to Case class conversion and vice versa. The definition of the trait is as below:
trait Converter[T] {
def convertFromJson(msg: String): Either[ConverterError, T]
def convertToJson(msg: T): String
}
Now, for one of the case classes that I have, I have defined the implementation like this:
object Converter extends DefaultJsonProtocol {
implicit object DefaultMessageConversions extends Converter[DefaultMessage] {
implicit val json = jsonFormat(DefaultMessage, "timestamp")
def convertFromJson(msg: String): Either[ConverterError, DefaultMessage] = {
try {
Right(msg.parseJson.convertTo[DefaultMessage])
}
catch {
case _: Exception => Left(ConverterError("Shit happens"))
}
}
def convertToJson(msg: DefaultMessage) = {
implicit val writes = Json.writes[DefaultMessage]
Json.toJson(msg).toString
}
}
def apply[T: Converter] : Converter[T] = implicitly
}
But I run into some compiler errors when I tried to build my project. I'm not sure what I did wrong?
[error] /Users/joesan/ingestion/src/main/scala/com/my/project/common/JsonMessageConversion.scala:28: could not find implicit value for evidence parameter of type com.my.project.common.JsonMessageConversion.Converter.JF[org.joda.time.DateTime]
[error] implicit val json = jsonFormat(DefaultMessage, "timestamp")
Here is how my case class look like:
case class DefaultMessage(timestamp: DateTime) extends KafkaMessage {
def this() = this(DateTime.now(DateTimeZone.UTC))
}

Your DefaultMessage uses org.joda.time.DateTime and spray-json does not know how to serialize/deserialize it out of the box.
Therefore you need to define a RootJsonFormat[DateTime] and bring it in implicit scope.
Here is an example implementation.

Related

Ambiguous Implicit Values for Case Class Option Parameter

I am going through some exercises I have invented on case classes and typeclasses. One of the problems I have faced is the following:
object Example extends App {
sealed trait Serializer[T] {
def serialize(seq: List[T]): String
}
implicit object StringSerializer extends Serializer[String] {
def serialize(seq: List[String]): String = seq.toString()
}
implicit object IntSerializer extends Serializer[Int] {
def serialize(seq: List[Int]): String = seq.toString()
}
case class Marker[T: Serializer](lst: Option[List[T]] = None)
Marker() // ambiguous implicit values: here...
}
Now this gives an error about ambiguous implicit values. I think this is related to a question I have asked before (albeit a different error message):
Type erasure in a nested list with a given context bound
Am I correct in that it is the same process at work here, even though the error message is different?
Compiler can't infer T. Try to specify T explicitly
Marker[String]() // compiles
Marker[Int]() // compiles
When you provide lst it can infer T itself
Marker(Some(List(1, 2)))
Marker(Some(List("a", "b")))
For the same reason
Marker(Option.empty[List[Int]])
Marker(Option.empty[List[String]])
Marker[Int](None)
Marker[String](None)
Marker(None: Option[List[Int]])
Marker(None: Option[List[String]])
compile while Marker(None) doesn't.
Alternatively you can prioritize your implicits
trait LowPrioritySerializer {
implicit object StringSerializer extends Serializer[String] {
def serialize(seq: List[String]): String = seq.toString()
}
}
object Serializer extends LowPrioritySerializer {
implicit object IntSerializer extends Serializer[Int] {
def serialize(seq: List[Int]): String = seq.toString()
}
}
Then IntSerializer will be tried firstly and StringSerializer will be tried secondly if IntSerializer didn't work (if type is different).

Implicit conversion not applying

I was trying to workout the classic example of converting arbitrary values into their Json representation and having compile time errors in case conversion is not defined.
So far, I have,
trait Json
trait ConvertableToJson[A] {
def toJson: Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
case class StrToJson(s: String) extends ConvertableToJson[StrToJson] {
override def toJson: Json = Str(s)
}
}
implicit def str2Json(s: String): StrToJson = StrToJson(s)
def toJson[A <: ConvertableToJson[A]](a: A) = a.toJson
println(toJson("some string"))
I expected the above code to work like:
toJson("some string") to fail to compile without the implicit def. Because String <: ConvertableToJson[String] is false.
But then to use, the implicit def and find Str2Json.
Str2Json <: ConvertableToJson[Str2Json] should be true.
However, this doesn't happen and compiler complains:
Error: Inferred type arguments [String] do not conform to method toJson's type parameter bounds [A <: scalaz.ConvertToJson.ConvertableToJson[A]]
println(toJson("dhruv"))
^
It'll be great if someone can help me correct my understanding
So there are two problems with your code. First of all String does not extend ConvertableToJson[String], which is what your last function call is trying to do.
Second case class StrToJson should extend ConvertableToJson[String] not ConvertableToJson[StrToJson].
Then your code be made to compile by using view-bounds <% (see the working example below). This however is a bad idea because view-bounds are being deprecated as a language feature, you should use type classes instead.
trait Json
trait ConvertableToJson[A] {
def toJson: Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
case class StrToJson(s: String) extends ConvertableToJson[String] {
override def toJson: Json = Str(s)
}
}
import Json._
implicit def str2Json(s: String): StrToJson = StrToJson(s)
def toJson[A <% ConvertableToJson[A]](a: A) = a.toJson
println(toJson("some string"))
Using typeclasses
trait Json
trait ConvertableToJson[A] {
// NOTE: this now takes a parameter
def toJson(a: A): Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
}
import Json._
// NOTE: Because toJson takes a parameter the implicit implementation can now be an object
implicit object Str2Json extends ConvertableToJson[String] {
override def toJson(a: String): Json = Str(a)
}
// NOTE: If you want to support the a.toJson syntax this implicit class adds it for all types with an implicit ConvertableToJson
implicit class ConvertableToJsonSyntax[A](a: A)(implicit ev: ConvertableToJson[A]) {
def toJson: Json = ev.toJson(a)
}
// NOTE: Now we use context-bounds instead of view-bounds
def toJson[A : ConvertableToJson](a: A) = a.toJson
// NOTE: we can expand the context-bounds
def toJson2[A](a: A)(implicit ev: ConvertableToJson[A]) = a.toJson
// NOTE: But since we have the type class instance now, we do not need the extra syntax
def toJson3[A](a: A)(implicit ev: ConvertableToJson[A]) = ev.toJson(a)
println(toJson("some string"))

spray-json can't find JsonReader for type List[T]

I'm creating custom json readers for case classes but it can't find implicit JsonReader type class for List[T] which is used in other case class.
When I checked DefaultJsonProtocol, it has implicit format for collections already;
implicit def listFormat[T :JsonFormat] = new RootJsonFormat[List[T]] {
def write(list: List[T]) = JsArray(list.map(_.toJson).toVector)
def read(value: JsValue): List[T] = value match {
case JsArray(elements) => elements.map(_.convertTo[T])(collection.breakOut)
case x => deserializationError("Expected List as JsArray, but got " + x)
}
}
Here is the simplified code;
case class Test(i: Int, d: Double)
case class ListOfTest(t: List[Test])
trait TestResultFormat extends DefaultJsonProtocol {
import CustomFormat._
implicit object TestJsonFormat extends RootJsonReader[Test] {
override def read(json: JsValue): Test = {
val jsObject = json.asJsObject
val jsFields = jsObject.fields
val i = jsFields.get("i").map(_.convertTo[Int]).getOrElse(0)
val d = jsFields.get("d").map(_.convertTo[Double]).getOrElse(0d)
Test(i, d)
}
}
implicit object ListOfTestJsonFormat extends RootJsonReader[ListOfTest] {
override def read(json: JsValue): ListOfTest = {
val jsObject = json.asJsObject
val jsFields = jsObject.fields
val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty)
ListOfTest(tests)
}
}
}
Here is the errors;
Error:(230, 53) not enough arguments for method convertTo: (implicit evidence$1: spray.json.JsonReader[List[com.xx.Test]])List[com.xx.Test].
Unspecified value parameter evidence$1.
val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty)
^
Error:(230, 53) Cannot find JsonReader or JsonFormat type class for List[com.xx.Test]
val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty)
^
I think the problem is related to the fact that the JsonReader for List[T] in DefaultJsonProtocol is a RootJsonFormat (not a RootJsonReader), which basically means you can read it and also write it. So, when you try to read a List[Item], it's expected that you are also able to write Items. So, you could use RootJsonFormat instead and throw an exception in case you try to write it (since you don't support it). For example:
import spray.json._
implicit object TestJsonFormat extends RootJsonFormat[Test] {
override def read(json: JsValue): Test = {
val jsObject = json.asJsObject
val jsFields = jsObject.fields
val i = jsFields.get("i").map(_.convertTo[Int]).getOrElse(0)
val d = jsFields.get("d").map(_.convertTo[Double]).getOrElse(0d)
Test(i, d)
}
override def write(obj: Test): JsValue = serializationError("not supported")
}
If you are aware of a clean solution involving only the readers, please do let me know because I ran into this problem myself and couldn't find anything else.
I have learned that limitation comes from spray-json:
spray-json 's type class infrastructure is build around the (Root)JsonFormat type, not the (Root)JsonReader. So you'll indeed have to provide a "Format" even if you are just reading.
Check here.
To overcome issue; I created another trait extends RootJsonFormat instead of reader and overrides write method with basically not implemented method.
trait EmptyWriterFormat[T] extends RootJsonFormat[T] {
override def write(o: T): JsValue = ???
}

Could not find implicit value for parameter x

Just when I thought I understood the basics of Scala's type system... :/
I'm trying to implement a class that reads the contents of a file and outputs a set of records. A record might be a single line, but it could also be a block of bytes, or anything. So what I'm after is a structure that allows the type of Reader to imply the type of the Record, which in turn will imply the correct Parser to use.
This structure works as long as MainApp.records(f) only returns one type of Reader. As soon as it can return more, I get this error:
could not find implicit value for parameter parser
I think the problem lies with the typed trait definitions at the top, but I cannot figure out how to fix the issue...
// Core traits
trait Record[T]
trait Reader[T] extends Iterable[Record[T]]
trait Parser[T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
trait TypeA
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
trait TypeB
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
// The "app"
object MainApp {
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File) = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
First off you must import the implicit object in order to use them:
import TypeA._
import TypeB._
That's not enough though. It seems like you're trying to apply implicits dynamically. That's not possible; they have to be found compile time.
If you import the objects as above and change the records so that the compiler finds the correct generic it will run fine:
def records(f: File) = new FileReader[TypeA](f)
But then it may not be what you were looking for ;)
The problem is that the return type of your records method is basically FileReader[_] (since it can return either FileReader[TypeA] or FileReader[TypeB]), and you don't provide an implicit argument of type Parser[Any]. If you remove the if-expression the return type is inferred to FileReader[TypeA], which works fine. I'm not sure what you're trying to do, but obviously the compiler can't select implicit argument based upon a type that is only known at runtime.
1) Using type with implicit inside as type parameter - doesn't bind this implicit to the host type, to do this change objects to the traits and mix them instead of generalizing (type-parametrizing):
def records(f: File) = {
if(true)
new FileReader(f) with TypeA
else
new FileReader(f) with TypeB
}
2) The parser should be in scope of function that calls parse. So you may try smthg like that:
def process(f: File) = {
val reader = records(f);
import reader._
reader foreach { r => parse(r) }
}
PlanB) Simpler alternative is to define type-parameter specific implicit methods inside the AppMain (or some trait mixed in), but it will work only if TypeA/TypeB is known on compile time, so records method can return concrete type:
implicit class TypeAParser(r: Record[TypeA]) {
def parse: Option[Int] = ???
}
implicit class TypeBParser(r: Record[TypeB]) {
def parse: Option[Int] = ???
}
def process[T <: TypeAorB](f: File) =
records[T](f).foreach(_.parse)
def recordsA[T <: TypeAorB](f: File) = new FileReader[T](f)
Here is, I think, the full set of modifications you need to do to get where I think you want to go.
import scala.io.Source
import java.io.File
import reflect.runtime.universe._
// Core traits
trait Record[+T]
trait Reader[+T] extends Iterable[Record[T]]
trait Parser[-T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations [unmodified]
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
sealed trait Alternatives
case class TypeA() extends Alternatives
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
case class TypeB() extends Alternatives
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
class ParseAlternator(parserA: Parser[TypeA], parserB: Parser[TypeB]) extends Parser[Alternatives] {
def parse(r: Record[Alternatives]): Option[Int] = r match {
case x: Record[TypeA #unchecked] if typeOf[Alternatives] =:= typeOf[TypeA] => parserA.parse(x)
case x: Record[TypeB #unchecked] if typeOf[Alternatives] =:= typeOf[TypeB] => parserB.parse(x)
}
}
object ParseAlternator {
implicit def parseAlternator(implicit parserA: Parser[TypeA], parserB: Parser[TypeB]): Parser[Alternatives] = new ParseAlternator(parserA, parserB)
}
// The "app"
object MainApp {
import ParseAlternator._
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File): Reader[Alternatives] = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
The gist of it is: all of this would be completely classsical if only your parse instance did not have to pattern-match on a generic type but dealt directly with an Alternative instead.
It's this limitation (inherited from the JVM) that scala can't properly pattern-match on an object of a parametric type that requires the reflection & typeOf usage. Without it, you would just have type alternatives for your content (TypeA, TypeB), which you would add to a sealed trait, and which you would dispatch on, in an implicit that produces a Parser for their supertype.
Of course this isn't the only solution, it's just what I think is the meeting point of what's closest to what you're trying to do, with what's most idiomatic.

Implicit resolution and companion objects for case classes

I'm trying to add an implicit value to (what I believe is) the companion object of a case class, but this implicit value is not found.
I'm trying to achieve something like the following:
package mypackage
object Main {
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = ...
serialize(out, caseClassInstance)
// the above line makes the compiler complain that there is no
// Serializer[MyCaseClass] in scope
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
...
}
}
object MyCaseClass {
// implicits aren't found here
implicit val serializer: Serializer[MyCaseClase] = ...
}
case class MyCaseClass(s: String) {
// some other methods
}
I've explicitly added the package here to show that both the MyCaseClass case class and object should be in scope. I know that the object is actually being constructed because I can get this to compile if I add
implicit val serializer = MyCaseClass.serializer
to main (though notably not if I add import MyCaseClass.serializer).
I'm concerned that the MyCaseClass object is not actually a companion of the case class, because if I explicitly define apply and unapply on the object and then attempt to call MyCaseClass.apply("string") in main, the compiler gives the following error:
ambiguous reference to overloaded definition,
both method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
and method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
match argument types (String)
val a = InputRecord.apply("string")
^
If it's not possible to take this approach, is there a way to use type classes with case classes without creating an implicit value every time it must be brought into scope?
EDIT: I'm using scala 2.10.3.
EDIT 2: Here's the example fleshed out:
package mypackage
import java.io.{DataOutput, DataOutputStream}
object Main {
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = new DataOutputStream(System.out)
serialize(out, caseClassInstance)
// the above line makes the compiler complain that there is no
// Serializer[MyCaseClass] in scope
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
implicitly[Serializer[T]].write(out, t)
}
}
object MyCaseClass {
// implicits aren't found here
implicit val serializer: Serializer[MyCaseClass] = new Serializer[MyCaseClass] {
override def write(out: DataOutput, t: MyCaseClass): Unit = {
out.writeUTF(t.s)
}
}
}
case class MyCaseClass(s: String) {
// some other methods
}
trait Serializer[T] {
def write(out: DataOutput, t: T): Unit
}
This actually compiles, though. I am getting this issue when using Scoobi's WireFormat[T] instead of Serializer, but can't provide a concise, runnable example due to complexity and the Scoobi dependency. I will try to create a more relevant example, but it seems as though the issue is not as general as I thought.
It turns out that the type class instances actually need to be implicit values, rather than objects. The MyCaseClass object above works because its serializer is assigned to an implicit value. However, this implementation
object MyCaseClass {
implicit object MyCaseClassSerializer extends Serializer[MyCaseClass] {
override def write(out: DataOutput, t: MyCaseClass): Unit = {
out.writeUTF(t.s)
}
}
}
fails with the error
Main.scala:9: error: could not find implicit value for evidence parameter of type mypackage.Serializer[mypackage.MyCaseClass]
serialize(out, caseClassInstance)
^
In my real code, I was using an auxiliary function to generate the Serializer[T] (see https://github.com/NICTA/scoobi/blob/24f48008b193f4e87b9ec04d5c8736ce0725d006/src/main/scala/com/nicta/scoobi/core/WireFormat.scala#L137). Despite the function having its own explicit return type, the type of the assigned value was not being inferred correctly by the compiler.
Below is the full example from the question with such a Serializer-generator.
package mypackage
import java.io.{DataOutput, DataOutputStream}
object Main {
import Serializer._
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = new DataOutputStream(System.out)
serialize(out, caseClassInstance)
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
implicitly[Serializer[T]].write(out, t)
}
}
object MyCaseClass {
import Serializer._
// does not compile without Serializer[MyCaseClass] type annotation
implicit val serializer: Serializer[MyCaseClass] =
mkCaseSerializer(MyCaseClass.apply _, MyCaseClass.unapply _)
}
case class MyCaseClass(s: String)
trait Serializer[T] {
def write(out: DataOutput, t: T): Unit
}
object Serializer {
// does not compile without Serializer[String] type annotation
implicit val stringSerializer: Serializer[String] = new Serializer[String] {
override def write(out: DataOutput, s: String): Unit = {
out.writeUTF(s)
}
}
class CaseClassSerializer[T, A : Serializer](
apply: A => T, unapply: T => Option[A]) extends Serializer[T] {
override def write(out: DataOutput, t: T): Unit = {
implicitly[Serializer[A]].write(out, unapply(t).get)
}
}
def mkCaseSerializer[T, A : Serializer]
(apply: A => T, unapply: T => Option[A]): Serializer[T] =
new CaseClassSerializer(apply, unapply)
}
This related, simple code below prints 1.
object A{
implicit def A2Int(a:A)=a.i1
}
case class A(i1:Int,i2:Int)
object Run extends App{
val a=A(1,2)
val i:Int=a
println(i)
}