Spray JSON:如何将隐式声明的对象转换为读写方法?

时间:2015-04-24 08:38:37

标签: scala spray scalatest spray-json

我目前正在努力为我的数据模型编写协议spray-json。要将JSON数据反序列化为我的数据传输对象,必须联系DAO以检查是否存在适当的对象,否则应抛出DeserializationException

到目前为止,我有以下内容:

object MyJsonProtocol extends DefaultJsonProtocol {

  implicit object MyDtoJsonFormat extends RootJsonFormat[MyDto] {

    override def write(obj: MyDto): JsValue = // Serialization implementation

    override def read(json: JsValue): MyDto = {
      // parse the JSON, get some parameters, let them be a, b, c
      dtoLookup(a, b, c) match {
        case Some(dto: MyDto) => dto
        case None => throw new DeserializationException("Cannot retrieve object from DAO")
      }
    }
  }

  def dtoLookup(a: SomeType, b: SomeOtherType, c: YetAnotherType)(implicit dao: MyDAO): Option[MyDto] = {
    // lookup the MyDTO with the dao instance
  }
}

我的测试如下:

class MyJsonProtocolTest extends FlatSpec with Matchers {

  implicit val MyDAO = // some test instance, can be a mock object

  "The protocol" should "serialize a DTO" in {
    val dto: MyDTO = ...
    dto.toJson.compactPrint should be("{...}")
  }
}

但是,编译器抱怨在尝试编译MyDAO时无法找到隐式MyJSONProtocol。在昨天我问的When testing Spray services with Scalatest, how to introduce implicit values?中,我被建议直接将隐式参数传递给方法,但我不能在此处执行此操作,因为read中定义了RootJsonFormat方法。

当我直接从我的测试代码调用dtoLookup方法时,它会成功。

那么,如何将MyDAO实例变为我的特殊JSON格式?

1 个答案:

答案 0 :(得分:0)

一个选项是使隐式参数成为正在使用的类之一的构造函数参数。这可能需要您将objects之一转换为class。然后,您可以在该类的伴随对象上创建一个get方法,该方法使用隐式范围来构造具有所需参数的类。

这与sprayscalatest无关,而只是涉及隐含和隐式范围的问题。这是一个简化版本:

object MyJsonProtocol {
  implicit object MyDtoJsonFormat {
    def read(x: Int) = dtoLookup
  }
  def dtoLookup(implicit x: Int) = x + 1
}

您可以考虑将其更改为:

class MyJsonProtocol(implicit x: Int) {
  implicit object MyDtoJsonFormat {
    def read(x: Int) = dtoLookup
  }
  def dtoLookup = x + 1
}

object MyJsonProtol {
    def get(implicit x: Int) = new MyJsonProtocol
}

然后你可以使用隐含的范围:

class MyJsonProtocolTest {
  implicit val x = 5
  val proto = MyJsonProtol.get
  val myReadValue = proto.MyDtoJsonFormat.read //6
}

您可以阅读有关隐式范围here的规则,尤其相关的可能是“Implicits来自哪里”部分。