我目前正在努力为我的数据模型编写协议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格式?
答案 0 :(得分:0)
一个选项是使隐式参数成为正在使用的类之一的构造函数参数。这可能需要您将objects
之一转换为class
。然后,您可以在该类的伴随对象上创建一个get
方法,该方法使用隐式范围来构造具有所需参数的类。
这与spray
或scalatest
无关,而只是涉及隐含和隐式范围的问题。这是一个简化版本:
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来自哪里”部分。