提前为交叉张贴表示歉意:我将这个问题提交给了喷雾用户列表,但是列表似乎已经被控制了,而且似乎没有人在家。希望这是一个更好的地点。
我很难用spray-json序列化复杂的数据结构。例如,一个简单的immutable.Map[String,String]可以正常工作,但是immutable.Map[String,Foo] (其中Foo是我定义的case类)不能工作。这些文档给我的印象是,我只需要为Foo定义一个Foo,我就准备好了。
下面是一些示例代码:
import spray.json._
import DefaultJsonProtocol._
case class Foo(hi: String)
object FooProtocol extends DefaultJsonProtocol {
implicit val fooFormat: JsonFormat[Foo] = jsonFormat1(Foo)
}
import FooProtocol._
object Thing {
def toSomething = {
Map("foo" -> Foo("bar"), "baz" -> Foo("quux")).toJson
}
}这将产生以下编译器错误:
[info] Compiling 1 Scala source to C:\spraytest\target\scala-2.10\classes...
[error] C:\spraytest\src\main\scala\Foo.scala:12: Cannot find JsonWriter or JsonFormat type class for scala.collection.immutable.Map[String,Foo]
[error] Map("foo" -> Foo("bar"), "baz" -> Foo("quux")).toJson
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 5 s, completed Jun 26, 2014 11:40:26 AM我很困惑。
发布于 2014-06-26 16:19:13
将您的FooProtocol重命名为Foo (这将使它成为免费的伙伴对象~>隐式范围),而只是继承import DefaultJsonProtocol._,例如:
import spray.json.DefaultJsonProtocol._
case class Foo(hi: String)
object Foo {
implicit val fooJson = jsonFormat1(Foo.apply)
}现在,您需要使用喷雾路径将正确的封送器导入范围。字符串的封送拆收器可以在spray中找到,Foos封送拆收器可以从它的伴生对象中找到,所以您需要导入的唯一东西是spray.httpx.SprayJsonSupport,这应该可以做到这一点。
或者你可以留下它,就像你拥有它,只剩下import FooProtocol。但从设计的角度来看,这并不是最好的解决方案。
更新
如果您查看toJson签名,您将看到它请求由jsonFormat方法生成的隐式JsonWriter。伙伴对象解决了这个问题,因为scala编译器将它包含到隐式解析作用域中,这是一个很好的实践,可以将您的关联放在那里,因为在这个过程中,您不需要进行显式导入,比如import FooProtocol._
至于Map和String封送拆收器,请看一下DefaultJsonProtocol特性,它扩展了BasicFormats和CollectionFormats,后者分别为String和Map提供了封送器。您唯一需要添加的是您自己的Foo类封送处理程序。
溶液
真正的问题是在多个封送机的范围内产生的。可以通过DefaultJsonProtocol的单个导入来访问所有的标准内嵌(在本例中是Map和String)。当您从这个特性扩展,然后将它导入到当前范围时,它也会导入所有标准封送器。因此,问题在于您的作用域有多个封送器,这就导致了scala编译器出现了一个含混不清的问题。
发布于 2014-06-26 16:16:49
AFAIK Map[String,_]没有默认编组。您可以尝试显式地转换对象toString (Map[String,String]可以序列化为Json),也可以为Map[String, Foo]提供封送处理程序。
发布于 2014-06-26 16:30:50
您必须创建一个对象来保存映射,然后可以序列化该对象。
import spray.json._
import DefaultJsonProtocol._
case class Foo(hi: String)
case class Bar( something: Map[String,Foo])
object FooBarProtocol extends DefaultJsonProtocol {
implicit val fooFormat: JsonFormat[Foo] = jsonFormat1(Foo)
implicit val barFormat: JsonFormat[Bar] = jsonFormat1(Bar)
}
object Thing {
def toSomething = {
Bar(Map("foo" -> Foo("bar"), "baz" -> Foo("quux"))).toJson
}
}https://stackoverflow.com/questions/24435370
复制相似问题