2013-03-29 13 views
20

ci sono due classi Foo e Bar. Foo contiene un campo di Bar. La domanda è: come posso implementare un jono implicito Writes per la classe ?Come implementare le scritture JSON implicite dell'oggetto incorporato in Play Framework 2.x

Ecco il codice:

package models 

import play.api.libs.json._ 

case class Foo(id: String, bar: Bar) 

object Foo { 
    implicit val implicitFooWrites = new Writes[Foo] { 
    def writes(foo: Foo): JsValue = { 
     Json.obj(
     "id" -> foo.id, 
     "bar" -> foo.bar 
    ) 
    } 
    } 
} 

case class Bar(x: String, y: Int) 

object Bar { 
    implicit val implicitBarWrites = new Writes[Bar] { 
    def writes(bar: Bar): JsValue = { 
     Json.obj(
     "x" -> bar.x, 
     "y" -> bar.y 
    ) 
    } 
    } 
} 

Quando provo a compilare, ottengo il seguente errore:

No Json deserializer found for type models.Bar. Try to implement an implicit Writes or Format for this type.

Non capisco questo errore di compilazione, da quando ho implementato un implicito Scrive per modelli. Classe. Qual è il problema qui?

risposta

29

E 'una questione di visibilità, quando si dichiara le scritture implicite [Foo] si sta non rendere visibile le scritture implicite [bar] ad esso:

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

import play.api.libs.json._ 

case class Bar(x: String, y: Int) 

object Bar { 
    implicit val implicitBarWrites = new Writes[Bar] { 
    def writes(bar: Bar): JsValue = { 
     Json.obj(
     "x" -> bar.x, 
     "y" -> bar.y 
    ) 
    } 
    } 
} 

case class Foo(id: String, bar: Bar) 

object Foo { 

    import Bar._ 

    implicit val implicitFooWrites = new Writes[Foo] { 
    def writes(foo: Foo): JsValue = { 
     Json.obj(
     "id" -> foo.id, 
     "bar" -> foo.bar 
    ) 
    } 
    }  
} 

// Exiting paste mode, now interpreting. 

import play.api.libs.json._ 
defined class Bar 
defined module Bar 
defined class Foo 
defined module Foo 

scala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1)))) 
res0: String = 
{ 
    "id" : "23", 
    "bar" : { 
    "x" : "x", 
    "y" : 1 
    } 
} 

Inoltre, se si sta utilizzando Gioca 2.1+ make verificare il nuovo utilizzo dei macro 2.10: http://www.playframework.com/documentation/2.1.0/ScalaJsonInception

Se si è soddisfatti dell'uso delle classi case e dei nomi di val/vars utilizzati come chiavi nell'output di json, come nel proprio caso BTW, quindi è possibile utilizzare le due one-liner:

che vi darà l'esatto equivalente:

scala> import play.api.libs.json._ 
import play.api.libs.json._ 

scala> case class Bar(x: String, y: Int) 
defined class Bar 

scala> case class Foo(id: String, bar: Bar) 
defined class Foo 

scala> implicit val barWrites = Json.writes[Bar] 
barWrites: play.api.libs.json.OWrites[Bar] = [email protected] 

scala> implicit val fooWrites = Json.writes[Foo] 
fooWrites: play.api.libs.json.OWrites[Foo] = [email protected] 

scala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1)))) 
res0: String = 
{ 
    "id" : "23", 
    "bar" : { 
    "x" : "x", 
    "y" : 1 
    } 
} 
+0

Nizza. Molte grazie. Basta dichiarare la classe "Bar" prima che la classe "Foo" risolva il problema. E grazie per il suggerimento con le nuove funzionalità di JSON di Play2.1. Questo riduce veramente il numero di righe da scrivere. – schub

+0

Sto cercando di capire come utilizzare mongodb reattivo seguendo il loro esempio e non si compila. Dopo aver letto questo post, sono stato in grado di modificare l'esistente e farlo pubblicare un utente. Sto usando 2.4 ora. Ci sono altre scorciatoie o modifiche che ora esistono in 2.4? – pitchblack408

Problemi correlati