【发布时间】:2014-11-13 08:56:14
【问题描述】:
将 Spray 与 spray-json 一起用于系统,版本:
"io.spray" %% "spray-json" % "1.2.6"
我不知道如何让自定义 JsonFormat 定义为喷雾路由处理的序列化工作。
我有两种不同的情况都失败了。
1.嵌套案例类
基本案例类 JSON 序列化工作正常
case class Something(a: String, b: String)
implicit val something2Json = jsonFormat3(Something)
但是,如果我在要序列化的案例类中有一个嵌套的案例类,我可以通过提供另一个隐式 JsonFormat 来解决编译问题,但在运行时它拒绝序列化
case class Subrecord(value: String)
case class Record(a: String, b: String, subrecord: Subrecord)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object SubrecordJsonFormat extends JsonFormat[Subrecord] {
def write(sub: Subrecord) = JsString(sub.value)
def read(value: JsValue) = value match {
case JsString(s) => Subrecord(s)
case _ => throw new DeserializationException("Cannot parse Subrecord")
}
}
implicit val record2Json = jsonFormat3(Record)
}
这将在运行时抛出 MappingException,说明子记录没有可用值
2。具有各种 0-N 案例扩展的特征
在这里,我有一个 trait 可以作为一组案例类的捕获类型。一些扩展类有 vals,而另一些没有 vals 并且是对象。当发生序列化时,似乎我的隐式定义的 JsonFormat 被完全忽略了,我只是给出了一个空的 JsObject,特别是当实际的底层类型是没有 val 的 case 对象之一时。
sealed trait Errors
sealed trait ErrorsWithReason extends Errors {
def reason: String
}
case class ValidationError(reason: String) extends ErrorsWithReason
case object EntityNotFound extends Errors
case class DatabaseError(reason: String) extends ErrorsWithReason
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object ErrorsJsonFormat extends JsonFormat[Errors] {
def write(err: Errors) = failure match {
case e: ErrorsWithReason => JsString(e.reason)
case x => JsString(x.toString())
}
def read(value: JsValue) = {
value match {
//Really only intended to serialize to JSON for API responses
case _ => throw new DeserializationException("Can't reliably deserialize Error")
}
}
}
}
鉴于上述情况,如果实际被序列化的类型是 EntityNotFound,那么序列化就变成了 RootJsonFormat 变成了{}。如果它是一个 ErrorsWithReason,那么它会变成一个 RootJsonFormat 变成 { "reason": "somevalue" }。我可能对 JsonFormat 定义应该如何工作感到困惑,但它似乎根本没有使用我的 write 方法,而是突然想出了如何自行序列化。
编辑
具体的序列化案例是使用读/反序列化,如:
entity(as[JObject]) { json =>
val extraction: A = json.extract[A]
}
并使用complete 指令进行写入/序列化。
感谢此处发布的第一个答案,我现在意识到我的 JsonDefaultProtocol 和 JsonFormat 实现是针对 spray-json 类的,同时反序列化中的实体指令提取使用的是 json4s JObject 而不是 spray-json JsObject。
【问题讨论】:
-
您是否将您的隐式放在扩展 DefaultJsonProtocol 的对象中,然后从该对象导入成员?示例:github.com/spray/…
-
一旦您可以使用 jsonprotocol 对象的扩展来序列化内部类。然后为外壳类创建一个对象,并将内部对象的成员导入其中。
-
对不起,我将编辑问题以反映这一点,但是是的,我所有的隐含都在导入的 DefaultJsonProtocol 扩展中。
标签: scala spray spray-json