我正在尝试将 json 字符串反序列化为通用集合。
我的代码看起来像这样:
class MyClass(json: String) {
def collectionType1: Set[Type1] = loadElements[Type1]
def collectionType2: Set[Type2] = ???
private def loadElements[T]: Set[T] = {
json.parseJson.convertTo[Set[T]]
}
}
我还定义了以下内容(我对“Type2”有完全相同的定义,案例类看起来不同):
case class Type1(p1: String, p2: String)
object Type1JsonProtocol extends DefaultJsonProtocol {
private implicit val collectionType1Format = jsonFormat2(Type1)
implicit object Type1SetJsonReader extends JsonReader[Set[Type1]] {
override def read(json: JsValue): Set[Type1] = json match {
case JsArray(elements) => elements.map(_.convertTo[Type1]) toSet
case x => deserializationError("Expected Collection as JsArray, but got " + x)
}
}
}
编译代码时出现如下错误:
Error:(25, 29) Cannot find JsonReader or JsonFormat type class for Set[T]
val res = json.convertTo[Set[T]]
^
和:
Error:(25, 29) not enough arguments for method convertTo: (implicit evidence$1: spray.json.JsonReader[Set[T]])Set[T].
Unspecified value parameter evidence$1.
val res = json.convertTo[Set[T]]
^
我显然遗漏了一些东西,但感觉它很小。有人知道吗?
谢谢!
最佳答案
下面是JsValue的convertTo函数的定义。
def convertTo[T](implicit evidence$1 : spray.json.JsonReader[T])
如您所见,您应该为 Type T 提供 JsonReader 作为隐式参数。
你无法决定什么是真实类型的 T 和它的 JsonReader,所以只需像这样再次使用隐式参数:
private def loadElements[T: JsonReader]: Set[T]
如果你不熟悉上面的风格,你可以像这样扩展代码:
private def loadElements[T](implicit p: JsonReader[T]): Set[T]
如果你想调用这个函数,你应该提供具体的类型而不是像这样的类型 T 和它的 JsonReader:
def collectionType1: Set[Type1] = {
import Type1JsonProtocol.*
loadElements[Type1]
}
通过这种技术,您可以在编译时而不是运行时检测到错误的反序列化问题。
关于scala - 无法使用 spray-json 反序列化通用集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34204153/