2013-05-01 13 views
5

Come si crea un oggetto Json con valori di tipi diversi?Come si crea un oggetto Json con valori di tipi diversi?

sto usando spray-JSON

Ecco il codice

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

Funziona ma sembra davvero pesante. C'è un modo per definire JSON con codice come questo?

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 

Non funziona dire che

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

che ottengo, il tipo di ciascun campo non è definito in fase di compilazione. Ma perché non dovrebbe funzionare se il serializzatore esegue comunque lo schema di corrispondenza?

Grazie!

+0

La libreria potrebbe supportare questo. Ma se no, ha una funzione 'implicita' che prende un' String' e lo converte in 'JsString' – Jatin

risposta

1

Si sta andando per l'approccio sbagliato qui. Per motivi di coerenza, vi incoraggio vivamente a utilizzare uno case class.

Diciamo che avete questo

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

e quindi si utilizza parse e decompose a che fare con questo.

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

E se si desidera serializzare un List[Image] a JSON:

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

di analizzare un elenco di immagini da JSON:

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

Utilizzando Option[SomeType] nel Imagecase class si occuperà di parametri mancanti/facoltativi automaticamente.

4

Sono d'accordo con @ alex23 che un approccio basato sulla classe del caso sarà migliore. Usando spray-json, definirai per prima cosa la struttura della classe case e un'estensione di DefaultJsonProtocol per descrivere le case case che vuoi essere in grado di serializzare. Che sarebbe simile a questa:

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

Poi, una versione modificata del vostro esempio sarà simile a questa:

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 

Il motivo per cui si stava vedendo che l'errore è che a spruzzo JSON non sa come per serializzare le liste di tuple che stai creando. Se si vuole veramente usare quella struttura e non seguire la rotta della classe case, allora si potrebbe cercare di fornire un serializzatore personalizzato per List [(String, Any)]. Controlla la sezione dei documenti spray-json intitolata "Fornire JsonFormats per altri tipi". Se vuoi seguire questa strada e hai bisogno di più aiuto, fammi sapere.

Problemi correlati