如何为通用 json-spray 解析器定义层次结构?

How do I define a hierarchy for a generic json-spray parser?

我们有一个 API,在响应中总是有一个 total-countentities,但是 entities 是不同的类型。我想要做的是使解析和转换为 case-类 更通用。

所以尝试使用以下类型

case class StandardReturn[A](
    `total-count`: Double,
    entities: List[A]
)

case class System(
    id: String,
    name: String
)

以及以下示例:

object SystemProtocol extends DefaultJsonProtocol {
  implicit val systemFormat: RootJsonFormat[System] = 
    jsonFormat2(System)
  implicit def entityFormat[A: JsonFormat] =
    jsonFormat(StandardReturn.apply[A], "total-count", "entities")
}
import SystemProtocol._

val response = """{
  "total-count": 10,
  "entities": [
    { "id": "1", "name": "me" }
  ]
}"""

class Example {
  def transform[A: JsonReader](entityString: String) =
    entityString.parseJson
      .convertTo[A]
      .entities  // Where I'm running into trouble
}
object Example {
  val transformed = new Example().transform[StandardReturn[System]](response)
}
Example.transformed

这是可以理解的给了我

Error:(34, 42) value entities is not a member of type parameter A
entityString.parseJson.convertTo[A].entities  // Where I'm running into trouble
                                    ^

我将如何设置案例 类 / 类型,以便 transform 可以确保 entities 在转换为类型 A 后将始终存在(其中 AStandardReturn[A])?我对scala的类型系统不太熟悉,谢谢大家的帮助。

在您的代码中,类型参数 A 除了绑定到 JsonReader 的上下文(JsonReader[A] 类型的隐式参数)之外没有边界。因此,正如您已经提到的,A 可以是任何东西,因此您不能调用 entities 方法。如果您转换为 StandardReturn[A] 而不是 A,这个问题就解决了。

def transform[A: JsonReader](entityString: String) =
  entityString.parseJson
    .convertTo[StandardReturn[A]] <- just convert to what you actually want
    .entities

此外,您必须将 new Example().transform[StandardReturn[System]](response) 中的类型参数替换为 System 而不是 StandardReturn[System],因为上述方法已更改。

编译器现在需要一个 JsonReader[StandardFormat[System]] 类型的隐式参数。但是在隐式作用域中,只有 JsonReader[System] 类型的 systemFormat(在 SystemProtocol 中)。编译器还没有放弃:他试图找到从 JsonReader[System]JsonReader[StandardFormat[System]] 的隐式转换,而这正是您定义的方法 entityFormat。是啊!

最后一点:如果将 jsonFormat(StandardReturn.apply[A], "total-count", "entities") 替换为 jsonFormat2(StandardReturn.apply[A]),您可以进一步简化方法 entityFormat,如 documentation.

中所述