I'm not a fan of bringing implicit parameters into my code so where I use them I want to encapsulate their use. So I am trying to define an object that both wraps up calls to spray-json with exception handling and contains default implicit JsonFormats for each of my model classes. However the implicit parameters are not resolved unless they are imported into the client, calling code, which is exactly where I don't want them to be. Here's what I have so far (which doesn't resolve the implicit formatters), is there a way I can get what I want to work?
package com.rsslldnphy.json
import com.rsslldnphy.models._
import spray.json._
object Json extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
def parse[T](s:String)(implicit reader: JsonReader[T]): Option[T] = {
try { Some(JsonParser(s).convertTo[T]) }
catch { case e: DeserializationException => None }
}
}
NB. a JsonFormat is a type of JsonReader
EDIT: Here's what I've written based on @paradigmatic's second suggestion (which I can't get to work, I still get Cannot find JsonReader or JsonFormat type class for T
). Am I missing something?
object Protocols extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
}
object Json {
def parse[T](s:String): Option[T] = {
import Protocols._
try { Some(JsonParser(s).convertTo[T]) }
catch { case e: DeserializationException => None }
}
}
For the record, this is a code snippet that does work, but that I'm trying to avoid as it requires too much of the client code (ie. it needs to have the implicits in scope):
object Json extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
}
object ClientCode {
import Json._
def person(s: String): Person = JsonParser(s).convertTo[Person]
}