周围范围的隐式参数解析

时间:2012-11-11 11:47:11

标签: scala implicits spray-json

我不喜欢将隐式参数加入到我的代码中,所以在我使用它们时我想封装它们的用法。所以我试图定义一个对象,它既包含对异常处理的spray-json的调用,又包含每个模型类的默认隐式JsonFormats。但是,隐式参数不会被解析,除非它们被导入到客户端,调用代码,这正是我不想要它们的地方。这是我到目前为止(没有解决隐式格式化程序),有没有办法可以得到我想要的工作?

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。 JsonFormat是一种JsonReader

编辑:这是我根据@ paradigmatic的第二个建议(我无法开始工作,我仍然得到Cannot find JsonReader or JsonFormat type class for T)所写的内容。我错过了什么吗?

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 }
  }
}

对于记录,这是一个可行的代码片段,但我正在努力避免,因为它需要太多的客户端代码(即它需要在范围内具有含义):

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]
}

1 个答案:

答案 0 :(得分:7)

您可以在随播对象中声明隐含:

object Person {
  implicit val personFormat: JReader[Person] = jsonFormat1(Person)
}
object Animal {
  implicit val animalFormat: JReader[Animal] = jsonFormat1(Animal)
}

隐式解决规则非常复杂。您可以在此blog post中找到更多信息。但是如果编译器正在寻找类型类T[A],它将在类/特性A的伴随对象中查看(很快或稍后)它。

编辑:如果问题只是范围问题"污染",您可以介绍一些大括号。使用您的代码示例,您可以将函数解析称为:

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 }
  }
}

object JsonFacade {
    def optParse[T]( s: String ): Option[T] = {
      import Json._
      parse[T]( s )
    }
}

这里暗示"污染"只有optParse方法。