2013-05-01 10 views
5

Jak utworzyć obiekt Json z wartościami różnych typów?Jak utworzyć obiekt Json z wartościami różnych typów?

używam sprayu-json

Oto kod

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) 
)) 

To działa, ale wygląda naprawdę ciężkie. Czy istnieje sposób zdefiniowania json z takim kodem?

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 

To nie działa mówiąc, że

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

które otrzymuję, typ każdego pola nie jest określona w czasie kompilacji. Ale dlaczego by nie działało, gdyby serialalizator i tak dopasował wzorce?

Dzięki!

+0

Biblioteka może wesprzeć to. Ale jeśli nie, użyj funkcji 'implicit', która pobiera ciąg' String' i konwertuje go na 'JsString' – Jatin

Odpowiedz

1

Wybieracie tu niewłaściwe podejście. Dla celów spójności zdecydowanie zachęcam do korzystania z case class.

Powiedzmy, że masz ten

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

A potem użyć parse i decompose sobie z tym poradzić.

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

A jeśli chcesz serializować List[Image] do JSON:

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

przeanalizować listę obrazów z JSON:

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

Korzystanie Option[SomeType] w Imagecase class zajmie się brakujące/opcjonalne parametry automatycznie.

4

Zgadzam się z @ alex23, że podejście oparte na klasach przypadków będzie lepsze. Używając spray-json, najpierw zdefiniujesz strukturę klasy case, a także rozszerzenie DefaultJsonProtocol, aby opisać klasy przypadków, które chcesz móc serializować. Że będzie wyglądać następująco:

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) 
} 

Następnie zmodyfikowana wersja swoim przykładzie wyglądałby następująco:

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 

powód, dla którego zostały obejrzeniu tego błędu jest to, że w sprayu-json nie wie, w jaki sposób serializować listy krotek, które tworzysz. Jeśli naprawdę chcesz użyć tej struktury i nie iść do klasy "case case", możesz zajrzeć do dostarczania niestandardowego serializera dla List [(String, Any)]. Zapoznaj się z sekcją w dokumentacji spray-json zatytułowanej "Zapewnienie JsonFormats dla innych typów". Jeśli chcesz iść tą drogą i potrzebujesz dodatkowej pomocy, daj mi znać.

Powiązane problemy