sowen
sowen

Reputation: 1088

How does circe parse a generic type object to Json?

Here is what I am trying to do

case class MessageModel (time: Long, content: String) {}
val message = MessageModel(123, "Hello World")
def jsonParser[A] (obj: A) : String = obj.asJson.noSpaces

println jsonParser[MessageModel](message)

this doesn't work, because it will complain Error:(13, 8) could not find implicit value for parameter encoder: io.circe.Encoder[A] obj.asJson.noSpaces ^

I kind of understand why it is happening, but is there a way to work around it?

Thanks

Upvotes: 6

Views: 3598

Answers (1)

Travis Brown
Travis Brown

Reputation: 139058

Encoding and decoding in circe are provided by type classes, which means that you have to be able to prove at compile time that you have a type class instance for A if you want to encode (or decode) a value of type A.

This means that when you write something like this:

import io.circe.syntax._

def jsonPrinter[A](obj: A): String = obj.asJson.noSpaces

You're not providing enough information about A for circe to be able to print values of that type. You can fix this with a context bound:

import io.circe.Encoder
import io.circe.syntax._

def jsonPrinter[A: Encoder](obj: A): String = obj.asJson.noSpaces

Which is Scala's syntactic sugar for something like this:

def jsonPrinter[A](obj: A)(implicit encoder: Encoder[A]): String =
  obj.asJson.noSpaces

Both of these will compile, and you can pass them a value of any type that has an implicit Encoder instance. For your MessageModel specifically, you could use circe's generic derivation, since it's a case class:

scala> import io.circe.generic.auto._
import io.circe.generic.auto._

scala> case class MessageModel(time: Long, content: String)
defined class MessageModel

scala> val message = MessageModel(123, "Hello World")
message: MessageModel = MessageModel(123,Hello World)

scala> jsonPrinter(message)
res0: String = {"time":123,"content":"Hello World"}

Note that this wouldn't work without the auto import, which is providing Encoder instances for any case class (or sealed trait hierarchy) whose members are all also encodeable.

Upvotes: 8

Related Questions