尽管导入,但无法在测试中找到参数化自定义 class 的 JSONReader

Unable to find JSONReader for parameterised-typed custom class in test, despite import

我有一个自定义class如下

object SafeList {
  def apply[A](x: List[A]): SafeList[A] = if (x == null) EmptyList else HasItems[A](x)
}

sealed abstract class SafeList[+A] extends Product with Serializable {
  def get: List[A]
}

final case class HasItems[+A](x: List[A]) extends SafeList[A] {
  def get = x
}

case object EmptyList extends SafeList[Nothing] {
  def get = Nil
}

还有一个 SafeList 的格式化程序,看起来像这样

...
import spray.json.DefaultJsonProtocol._

trait SafeCollectionFormats {
  implicit def safeListFormat[A: RootJsonFormat] = new RootJsonFormat[SafeList[A]] {

    def read(json: JsValue): SafeList[A] = {
      val list: List[A] = listFormat[A].read(json)
      SafeList[A](list)
    }

    def write(sl: SafeList[A]): JsValue =
      listFormat[A].write(sl.get)
  }
}
object SafeCollectionFormats extends SafeCollectionFormats

然后编译。

但是当我为格式化程序添加测试时,就像这样....

...
import spray.json.DefaultJsonProtocol._
import marshalling.SafeCollectionFormats._
...

  "Unmarshalling a json array with items" should "produce a SafeList with items" in {
    val json: JsValue = JsArray(JsString("a"), JsString("b"), JsString("c"))
    val list = List("a", "b", "c")

    val result = json.convertTo[SafeList[String]]

    assertResult(list)(result)
  }

...

我得到以下编译错误

Error:(14, 32) Cannot find JsonReader or JsonFormat type class for myapp.types.SafeList[String]
    val result = json.convertTo[SafeList[String]]
                               ^

认为 this 答案中可能有一些东西可以帮助我,但对我来说有点高级。我认为我的隐式 safeListFormat 我的 SafeList 的 JsonReader,我正在将它导入我的 Spec。我不知道参数化类型是否令人困惑?

知道我做错了什么吗?

编辑: 虽然我目前的测试是创建一个字符串安全列表,但最终目的是创建我的域对象的安全列表。我将需要添加第二个测试来构建 MyObjects 的 JsArray。因此 A - 在 JSON 术语中的类型将有所不同。我的 SafeList 需要处理像字符串这样的简单对象和领域对象。我想我可能会把它作为第二个 SO 问题提出,但我在这里提到它是为了上下文

它只需要一点点改动就对我有用:我 SafeCollectionFormats 扩展了 DefaultJsonProtocol

我还必须将 safeListFormat 的上下文绑定更改为 [A: JsonFormat]

trait SafeCollectionFormats extends DefaultJsonProtocol {
  implicit def safeListFormat[A: JsonFormat] = new RootJsonFormat[SafeList[A]] {

    def read(json: JsValue): SafeList[A] = {
      val list: List[A] = listFormat[A].read(json)
      SafeList[A](list)
    }

    def write(sl: SafeList[A]): JsValue =
      listFormat[A].write(sl.get)
  }
}

object SafeCollectionFormats extends SafeCollectionFormats

希望对您有所帮助。