2013-05-01 8 views
5

Wie erstellen Sie Json-Objekt mit Werten verschiedener Typen?Wie erstellen Sie Json-Objekt mit Werten verschiedener Typen?

Ich bin mit Spray-json

Hier ist der Code

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

Es funktioniert, aber sieht wirklich schwer. Gibt es eine Möglichkeit, Json mit Code wie diesem zu definieren?

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 

Es funktioniert nicht sagen, dass

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

Was ich bekommen, geben Sie jedes Feld nicht bei der Kompilierung definiert ist. Aber warum würde es nicht funktionieren, wenn der Serializer die Mustererkennung trotzdem durchführt?

Danke!

+0

Die Bibliothek könnte dies unterstützen. Wenn nicht, habe eine "implizite" Funktion, die eine "Zeichenfolge" akzeptiert und sie in "JsString" umwandelt – Jatin

Antwort

1

Sie sind hier für die falsche Vorgehensweise. Aus Gründen der Konsistenz empfehle ich Ihnen dringend, eine case class zu verwenden.

Sagen Sie bitte diese

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

haben Und dann verwenden Sie parse und decompose damit umgehen.

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

Und wenn Sie wollen ein List[Image] zu JSON serialisiert:

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

Um eine Liste der Bilder von JSON zu analysieren:

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

Mit Option[SomeType] im Imagecase class wird befassen sich mit fehlende/optionale Parameter automatisch.

4

Ich stimme @ @ alex23 zu, dass ein auf der Fallklasse basierender Ansatz besser sein wird. Mit spray-json definieren Sie zuerst Ihre Fallklassenstruktur sowie eine Erweiterung von DefaultJsonProtocol, um die Fallklassen zu beschreiben, die Sie serialisieren können. Das würde wie folgt aussehen:

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

Dann wird eine modifizierte Version von Ihrem Beispiel würde wie folgt aussehen:

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 

Der Grund, warum Sie diese Fehler wurden zu sehen, dass Spray-json weiß nicht, wie um die Listen der Tupel, die Sie erstellen, zu serialisieren. Wenn Sie diese Struktur wirklich verwenden und die Fallklassenroute nicht verwenden möchten, können Sie einen benutzerdefinierten Serializer für List [(String, Any)] bereitstellen. Schauen Sie sich den Abschnitt in der "JsonFormats für andere Typen" an. Wenn Sie diesen Weg gehen und mehr Hilfe brauchen, lassen Sie es mich wissen.

Verwandte Themen