2013-03-29 9 views
20

istnieją dwie klasy Foo i Bar. Foo zawiera pole Bar. Pytanie brzmi, jak zaimplementować domyślny json Writes dla klasy Foo?Jak zaimplementować ukryte zapisy Json obiektu osadzonego w Play Framework 2.x

Oto kod:

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

Kiedy próbuję skompilować, pojawia się następujący błąd:

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

Nie rozumiem ten błąd kompilatora, ponieważ realizowane niejawna Writes dla modeli. Jaki jest tutaj problem?

Odpowiedz

29

To kwestia widoczności, przy deklarowaniu ukryte Writes [Foo] nie jesteś co widoczne ukryte Writes [bar] do niego:

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

Ponadto, jeśli używasz Zagraj 2.1+ markę upewnij się, że sprawdziłeś zupełnie nowe zastosowanie makr 2.10: http://www.playframework.com/documentation/2.1.0/ScalaJsonInception

Jeśli jesteś zadowolony z używania klas przypadków i nazw val/vars używanych jako klucze w wyjściu json, tak jak w twoim W przypadku BTW można użyć dwóch jednokomorowych:

implicit val barFormat = Json.writes[Bar] 
implicit val fooFormat = Json.writes[Foo] 

To daje dokładny odpowiednik:

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

Nicea. Wielkie dzięki. Deklaracja klasy "Bar" przed klasą "Foo" rozwiązuje problem. I dzięki za podpowiedź z nowymi funkcjami jsonowymi Play2.1. To naprawdę skraca liczbę linii do napisania. – schub

+0

Próbuję dowiedzieć się, jak korzystać z reaktywnego mongodb, podążając za ich przykładem i nie skompilowałoby się. Po przeczytaniu tego posta mogłem zmodyfikować istniejący i pobrać go, aby opublikować użytkownika. Używam teraz 2,4. Czy istnieją inne skróty lub zmiany, które istnieją już w wersji 2.4? – pitchblack408

Powiązane problemy