如何使用不同类型的值创建Json对象?
我正在使用spray-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
^
我得到的,每个字段的类型都没有在编译时定义。但是,如果序列化器无论如何进行模式匹配,为什么它不会起作用呢?
谢谢!
答案 0 :(得分: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不知道如何序列化你正在创建的元组列表。如果你真的想使用那个结构而不是case case路由,那么你可以考虑为List [(String,Any)]提供一个自定义的序列化器。查看名为“为其他类型提供JsonFormats”的spray-json文档中的部分。如果你想走这条路并需要更多帮助,请告诉我。
答案 1 :(得分:1)
你在这里采取错误的做法。出于一致性目的,我强烈建议您使用case class
。
说你有这个
case class Image(
url: String,
size: Double,
properties: Map[String][String]
optionalProperty: Option[String]
// etc.
);
然后您使用parse
和decompose
来解决此问题。
val image = parse(jsonString).extract[Image]; // extracts an Image from JSON.
val jsonForImage: JValue = decompose(image); // serializes an Image to JSON.
如果您想将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]
Image
中使用case class
会自动处理缺失/可选参数。