首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >很难用喷雾-json序列化immutable.Map

很难用喷雾-json序列化immutable.Map
EN

Stack Overflow用户
提问于 2014-06-26 16:07:18
回答 3查看 3.1K关注 0票数 0

提前为交叉张贴表示歉意:我将这个问题提交给了喷雾用户列表,但是列表似乎已经被控制了,而且似乎没有人在家。希望这是一个更好的地点。

我很难用spray-json序列化复杂的数据结构。例如,一个简单的immutable.Map[String,String]可以正常工作,但是immutable.Map[String,Foo] (其中Foo是我定义的case类)不能工作。这些文档给我的印象是,我只需要为Foo定义一个Foo,我就准备好了。

下面是一些示例代码:

代码语言:javascript
复制
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
  }
}

这将产生以下编译器错误:

代码语言:javascript
复制
[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

我很困惑。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-06-26 16:19:13

将您的FooProtocol重命名为Foo (这将使它成为免费的伙伴对象~>隐式范围),而只是继承import DefaultJsonProtocol._,例如:

代码语言:javascript
复制
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特性,它扩展了BasicFormatsCollectionFormats,后者分别为String和Map提供了封送器。您唯一需要添加的是您自己的Foo类封送处理程序。

溶液

真正的问题是在多个封送机的范围内产生的。可以通过DefaultJsonProtocol的单个导入来访问所有的标准内嵌(在本例中是Map和String)。当您从这个特性扩展,然后将它导入到当前范围时,它也会导入所有标准封送器。因此,问题在于您的作用域有多个封送器,这就导致了scala编译器出现了一个含混不清的问题。

票数 4
EN

Stack Overflow用户

发布于 2014-06-26 16:16:49

AFAIK Map[String,_]没有默认编组。您可以尝试显式地转换对象toString (Map[String,String]可以序列化为Json),也可以为Map[String, Foo]提供封送处理程序。

票数 1
EN

Stack Overflow用户

发布于 2014-06-26 16:30:50

您必须创建一个对象来保存映射,然后可以序列化该对象。

代码语言:javascript
复制
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
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24435370

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档