2012-11-27 12 views
6

Ho una semplice domanda riguardante il rendering dell'oggetto JSON da una classe Scala. Perché devo implementare il deserializzatore (leggi, scrivi).Rendering JSON con Play! e Scala

Ho la seguente classe di caso:

case class User(firstname:String, lastname:String, age:Int) 

E nel mio controller:

val milo:User = new User("Sam","Fisher",23); 

Json.toJson(milo); 

ottengo errore di compilazione: No JSON deserializzatore trovato per il tipo models.User. Prova ad implementare scritture o formati impliciti per questo tipo.

Nel mio precedente progetto ho dovuto implementare un lettore, un oggetto writer nella classe per farlo funzionare e trovo molto fastidioso.

object UserWebsite { 
    implicit object UserWebsiteReads extends Format[UserWebsite] { 

    def reads(json: JsValue) = UserWebsite(
     (json \ "email").as[String], 
     (json \ "url").as[String], 
     (json \ "imageurl").as[String]) 

    def writes(ts: UserWebsite) = JsObject(Seq(
     "email" -> JsString(ts.email), 
     "url" -> JsString(ts.url), 
     "imageurl" -> JsString(ts.imageurl))) 
    } 
} 

risposta

3

Se si utilizza il gioco 2.0.x si può fare

import com.codahale.jerkson.Json._ 

generate(milo) 

generano utilizza la riflessione per farlo.

Nella riproduzione 2.1 è possibile utilizzare Json.writes per creare una macro per l'oggetto implicito che si doveva creare. Nessuna riflessione di runtime necessaria!

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 

implicit val userWrites = Json.writes[User] 
Json.toJson(milo) 
9

Consiglio vivamente di passare a giocare a 2.1-RC1 perché qui, gli scrittori JSON/lettori sono molto semplici da definire (maggiori dettagli here)

Ma, al fine di aiutare a evitare alcuni errori, Ti darò un suggerimento con le importazioni: - usa solo queste importazioni! (Notare che json.Reads non è incluso)

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 
import play.api.libs.json.Writes._ 

e devi solo scrivere il codice per la scrittura/lettura la classe da/JSON (ovviamente si avrà User invece di Address:

implicit val addressWrites = Json.writes[Address] 
implicit val addressReads = Json.reads[Address] 

Ora, essi saranno utilizzati automaticamente:

Esempio di scrittura:

Ok(Json.toJson(entities.map(s => Json.toJson(s)))) 

Esempio di leggere (io ho messo il mio esempio di fare POST per la creazione di un'entità con la lettura JSON dal corpo) si prega di notare addressReads usato qui

def create = Action(parse.json) { request => 
     request.body.validate(addressReads).map { entity => 
      Addresses.insert(entity) 
      Ok(RestResponses.toJson(RestResponse(OK, "Succesfully created a new entity."))) 
     }.recover { Result => 
      BadRequest(RestResponses.toJson(RestResponse(BAD_REQUEST, "Unable to transform JSON body to entity."))) 
     } 
} 

In conclusione, hanno cercato (e riuscirono) a fare cose molto semplici per quanto riguarda JSON.

0

Ho usato jerkson (che fondamentalmente è wrapper per jackson) nel mio progetto per convertire oggetti in stringa json.

Il modo più semplice per farlo è:

import com.codehale.jerkson.Json._ 
... 
generate(milo) 
... 

Se è necessario configurare l'ObjectMapper (ad esempio l'aggiunta di serializzatore personalizzato/deserializzatore, configurare il formato di output, ecc), puoi farlo creando oggetti che estendono la classe com.codehale.jerkson.Json.

package utils 

import org.codehaus.jackson.map._ 
import org.codehaus.jackson.{Version, JsonGenerator, JsonParser} 
import com.codahale.jerkson.Json 
import org.codehaus.jackson.map.module.SimpleModule 
import org.codehaus.jackson.map.annotate.JsonSerialize 

object CustomJson extends Json { 

    val module = new SimpleModule("CustomSerializer", Version.unknownVersion()) 

    // --- (SERIALIZERS) --- 
    // Example: 
    // module.addSerializer(classOf[Enumeration#Value], EnumerationSerializer) 
    // --- (DESERIALIZERS) --- 
    // Example: 
    // module.addDeserializer(classOf[MyEnumType], new EnumerationDeserializer[MyEnumType](MyEnumTypes)) 

    mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL) 
    mapper.setSerializationConfig(mapper.getSerializationConfig.without(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES)) 
    mapper.registerModule(module) 
} 

Per utilizzarlo nei codici:

import utils.CustomJson._ 
... 
generate(milo) 
... 
0

In realtà, questo è molto semplice. In primo luogo l'importazione:

import play.api.libs.json._ 

Grazie al fatto che l'utente è una classe caso è possibile creare automaticamente JSON scrive utilizzando Json.writes []:

val milo:User = new User("Millad","Dagdoni",23) 
implicit val userImplicitWrites = Json.writes[User] 
Json.toJson(milo) 

non ho trovato nella documentazione , ma ecco il link all'api: http://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.libs.json.Json $

0

Nel tuo caso, utilizzerei la macro JSON.format.

import play.api.libs.json._ 
implicit val userFormat = Json.format[User] 
val milo = new User("Sam", "Fisher", 23) 
val json = Json.toJson(milo) 
Problemi correlati