0

我正在编写一个 RESTful 接口,我想为 Ember 数据编组和解组 JSON。问题是 Ember Data 想要实体名称,而我尝试过的两个库,spray-json 和 json4s,似乎并不容易做到这一点。

所需的 Ember 数据格式

{
  "coursePhoto": {
    "photoId": 1
  }
}

当前默认格式:

{"photoId":15}

这应该来自一个案例类:

case class CoursePhoto(photoId: Long)

我确实使用以下自定义代码运行它:

object PtolemyJsonProtocol extends DefaultJsonProtocol {
  implicit object CoursePhotoFormat extends RootJsonFormat[CoursePhoto] {
  def write(cp: CoursePhoto) =
    JsObject("CoursePhoto" -> JsObject("photoId" -> JsNumber(cp.photoId)))  
  def read(value: JsValue) = value match {
    case coursePhotoJsObject: JsObject => {
      CoursePhoto(coursePhotoJsObject.getFields("CoursePhoto")(0).asJsObject
      .getFields("photos")(0).asInstanceOf[JsArray].elements(0)
      .asInstanceOf[JsNumber].value.toLong)
    }            
    case _ => deserializationError("CoursePhoto expected")
  }
}

这段代码看起来非常脆弱和丑陋,所有的asInstanceOfand (0).

鉴于我正在使用 Scala 编写 Spray 什么是获得命名根 JSON 输出的好方法?我很高兴使用任何与 Spray 完美集成且性能合理的 JSON 库来做到这一点。

4

2 回答 2

0

以下是否解决了您的问题?

scala> import spray.json._
import spray.json._

scala> import DefaultJsonProtocol._
import DefaultJsonProtocol._

scala> case class CoursePhoto(photoId: Long)
defined class CoursePhoto

scala> case class CoursePhotoEmber(coursePhoto: CoursePhoto)
defined class CoursePhotoEmber

scala> implicit val jsonFormatCoursePhoto = jsonFormat1(CoursePhoto)
jsonFormatCoursePhoto: spray.json.RootJsonFormat[CoursePhoto] = spray.json.ProductFormatsInstances$$anon$1@6f5d66b6

scala> implicit val jsonFormatCoursePhotoEmber = jsonFormat1(CoursePhotoEmber)
jsonFormatCoursePhotoEmber: spray.json.RootJsonFormat[CoursePhotoEmber] = spray.json.ProductFormatsInstances$$anon$1@401a0d22

scala> """{ "coursePhoto": { "photoId": 1 } }""".parseJson.convertTo[CoursePhotoEmber]
res0: CoursePhotoEmber = CoursePhotoEmber(CoursePhoto(1))

scala> res0.toJson
res1: spray.json.JsValue = {"coursePhoto":{"photoId":1}}
于 2014-06-07T20:20:28.713 回答
0

这个问题让我想知道是否有可能以可重用的方式做到这一点。我相信我已经找到了一种合理的方法来为多种类型执行此操作。

object PtolemyJsonProtocol extends DefaultJsonProtocol {
  implicit val CoursePhotoFormat = new NamedRootFormat("CoursePhoto", jsonFormat1(CoursePhoto))
}
import PtolemyJsonProtocol._

class NamedRootFormat[T](rootName: String, delegate: RootJsonFormat[T]) extends RootJsonFormat[T] {
  def write(obj: T): JsValue = {
    JsObject((rootName, delegate.write(obj)))
  }
  def read(json: JsValue): T = json match {
    case parentObject: JsObject => {
      delegate.read(parentObject.getFields(rootName).head)
    }
    case _ => deserializationError("CoursePhoto expected")
  }
}
于 2014-06-08T14:20:50.213 回答