6

如何创建具有不同类型值的 Json 对象?

我正在使用喷雾 json

这是代码

val images : List[JsObject] = fetchImageUrls(url).map((url: String) => {
  JsObject(List(
        "link_path" -> JsString(url),
        "display_name" -> JsString("image"),
        "size" -> JsString(""),
        "modified" -> JsString(""),
        "thumbnail" -> JsString(url),
        "filename" -> JsString("image"),
        "is_dir" -> JsBoolean(x = false),
        "thumb_exists" -> JsBoolean(x = true)) )
  })

val jsonAst: JsObject = JsObject(List(
  "client" -> JsString("urlimages"),
  "view" -> JsString("thumbnails"),
  "contents" -> JsArray(images)
))

它有效,但看起来很重。有没有办法用这样的代码定义json?

val images : List[List[(String, Any)]] = fetchImageUrls(url).map((url: String) => {
  List(
    "link_path" -> url,
    "display_name" -> "image",
    "size" -> "",
    "modified" -> "",
    "thumbnail" -> url,
    "filename" -> "image",
    "is_dir" -> false,
    "thumb_exists" -> true)
})

val jsonAst = List(
  "client" -> "urlimages",
  "view" -> "thumbnails",
  "contents" -> images
).toJson

这么说是不行的

Cannot find JsonWriter or JsonFormat type class for List[(String, Object)]
    ).toJson
      ^

我得到,每个字段的类型在编译时没有定义。但是,如果序列化程序仍然进行模式匹配,为什么它不起作用呢?

谢谢!

4

2 回答 2

4

我同意@alex23 的观点,即基于案例类的方法会更好。使用 spray-json,您将首先定义您的案例类结构以及 DefaultJsonProtocol 的扩展来描述您希望能够序列化的案例类。看起来像这样:

case class Image(link_path:String, display_name:String, size:Option[String], 
  modified:Option[String], thumbnail:String, filename:String, is_dir:Boolean, thumb_exists:Boolean)
object Image  

case class UrlImages(client:String, view:String, contents:List[Image])
object UrlImages

object MyJsonProtocol extends DefaultJsonProtocol {
  implicit val imageFormat = jsonFormat8(Image.apply)
  implicit val urlImagesFormat = jsonFormat3(UrlImages.apply)
}  

然后,您的示例的修改版本将如下所示:

import MyJsonProtocol._
val images : List[Image] = fetchImageUrls(url).map((url: String) => {
  Image(url, "image", None, None, url, "image", false, true)      
})

val jsonAst = UrlImages("urlimages", "thumbnails", images).toJson

您看到该错误的原因是 spray-json 不知道如何序列化您正在创建的元组列表。如果您真的想使用该结构而不是使用案例类路线,那么您可以考虑为 List[(String,Any)] 提供自定义序列化程序。查看 spray-json 文档中标题为“为其他类型提供 JsonFormats”的部分。如果您想走这条路并需要更多帮助,请告诉我。

于 2013-05-01T11:58:03.137 回答
1

您在这里采用错误的方法。出于一致性目的,我强烈建议您使用case class.

说你有这个

case class Image(
    url: String,
    size: Double,
    properties: Map[String][String]
    optionalProperty: Option[String]
    // etc.
);

然后你使用parseanddecompose来处理这个。

val image = parse(jsonString).extract[Image]; // extracts an Image from JSON.
val jsonForImage: JValue = decompose(image);  // serializes an Image to JSON.

如果您想将 a 序列化为List[Image]JSON:

def serialize(images: List[Image]) : JValue = {
    for (image <- images) 
       yield decompose(image);
};

要从 JSON 解析图像列表:

val images: List[Image] = parse(jsonString).extract[List[Image]];

使用Option[SomeType]inImage case class将自动处理缺失/可选参数。

于 2013-05-01T11:17:13.717 回答