spray-json 找不到 List[T] 类型的 JsonReader
Posted
技术标签:
【中文标题】spray-json 找不到 List[T] 类型的 JsonReader【英文标题】:spray-json can't find JsonReader for type List[T] 【发布时间】:2016-09-22 11:48:58 【问题描述】:我正在为案例类创建自定义 json 阅读器,但它找不到用于其他案例类的 List[T] 的隐式 JsonReader 类型类。
当我检查 DefaultJsonProtocol 时,它已经具有集合的隐式格式;
implicit def listFormat[T :JsonFormat] = new RootJsonFormat[List[T]]
def write(list: List[T]) = JsArray(list.map(_.toJson).toVector)
def read(value: JsValue): List[T] = value match
case JsArray(elements) => elements.map(_.convertTo[T])(collection.breakOut)
case x => deserializationError("Expected List as JsArray, but got " + x)
这里是简化的代码;
case class Test(i: Int, d: Double)
case class ListOfTest(t: List[Test])
trait TestResultFormat extends DefaultJsonProtocol
import CustomFormat._
implicit object TestJsonFormat extends RootJsonReader[Test]
override def read(json: JsValue): Test =
val jsObject = json.asJsObject
val jsFields = jsObject.fields
val i = jsFields.get("i").map(_.convertTo[Int]).getOrElse(0)
val d = jsFields.get("d").map(_.convertTo[Double]).getOrElse(0d)
Test(i, d)
implicit object ListOfTestJsonFormat extends RootJsonReader[ListOfTest]
override def read(json: JsValue): ListOfTest =
val jsObject = json.asJsObject
val jsFields = jsObject.fields
val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty)
ListOfTest(tests)
这是错误;
Error:(230, 53) not enough arguments for method convertTo: (implicit evidence$1: spray.json.JsonReader[List[com.xx.Test]])List[com.xx.Test].
Unspecified value parameter evidence$1.
val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty)
^
Error:(230, 53) Cannot find JsonReader or JsonFormat type class for List[com.xx.Test]
val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty)
^
【问题讨论】:
【参考方案1】:我认为问题与DefaultJsonProtocol
中List[T]
的JsonReader
是RootJsonFormat
(不是RootJsonReader
)这一事实有关,这基本上意味着您可以阅读它也可以编写它。因此,当您尝试读取List[Item]
时,预计您也可以写入Item
s。因此,您可以改用RootJsonFormat
并抛出异常以防您尝试编写它(因为您不支持它)。例如:
import spray.json._
implicit object TestJsonFormat extends RootJsonFormat[Test]
override def read(json: JsValue): Test =
val jsObject = json.asJsObject
val jsFields = jsObject.fields
val i = jsFields.get("i").map(_.convertTo[Int]).getOrElse(0)
val d = jsFields.get("d").map(_.convertTo[Double]).getOrElse(0d)
Test(i, d)
override def write(obj: Test): JsValue = serializationError("not supported")
如果您知道仅涉及读者的干净解决方案,请告诉我,因为我自己遇到了这个问题并且找不到其他任何东西。
【讨论】:
感谢您的回答。我刚刚从github问题中学到了它。对于干净的解决方案,请检查我的答案,我认为它不是很干净,但我不想总是覆盖 write 方法,因为我们有很多自定义格式化程序,它的开销很大,所以我创建了一个基本特征来做到这一点。跨度> 我明白了 :) 我很久以前就遇到过这个问题,我有点习惯于重写(未使用的)写入方法。谢谢。【参考方案2】:我了解到限制来自spray-json:
spray-json 的类型类基础结构是围绕 (Root)JsonFormat 类型构建的,而不是 (Root)JsonReader。因此,即使您只是在阅读,也确实必须提供“格式”。
Check here.
克服问题;我创建了另一个 trait 扩展了 RootJsonFormat 而不是 reader,并用基本上未实现的方法覆盖了 write 方法。
trait EmptyWriterFormat[T] extends RootJsonFormat[T]
override def write(o: T): JsValue = ???
【讨论】:
以上是关于spray-json 找不到 List[T] 类型的 JsonReader的主要内容,如果未能解决你的问题,请参考以下文章
Spray-json 用于 List 上的普通类(非大小写)
SerializationException:在 c# unity3d 中找不到类型'System.Collections.Generic.List`1