2

我不喜欢将隐式参数带入我的代码中,所以我想在使用它们的地方封装它们的使用。因此,我试图定义一个对象,该对象既包含对 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 }
  }
}

注意。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]
}
4

1 回答 1

7

您可以在伴随对象中声明隐式:

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

隐式解析规则非常复杂。您可以在此博客文章中找到更多信息。但是如果编译器正在寻找一个 typeclass T[A],它会(迟早)在 class/trait 的伴生对象中寻找它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方法。

于 2012-11-11T11:53:32.607 回答