2013-07-23 14 views
9

W wersji 2.1 używamy czegoś takiego jak poniżej, aby uzyskać obiekt istot z JSON poprzez czytanie.Odtwórz Kombinatory JSON

implicit val creatureReads = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean] and 
    (__ \ "weight").read[Float] 
)(Creature.apply _) 

krewny nowego w Scala Próbuję zrozumieć, czy istnieje jakiś inny sposób, aby zbudować obiekt Creature bez użycia metody Zastosuj? Czy byłoby możliwe posiadanie anonimowej funkcji do stworzenia obiektu zamiast polegania na wniosku?

Mam przypadki użycia, w których większość pól w moich obiektach może być niedostępna, ale chciałbym nadal budować obiekt z tego, co mam. Czy lepiej jest po prostu zdefiniować jeden READ dla obiektu i użyć readnullable dla każdego z pól?

Mogę również mieć złożone warunki warunkowe, więc czy byłoby czystsze zdefiniowanie niestandardowych funkcji do ich zbudowania zamiast próby przechwycenia wszystkich przypadków w jednym Czytniku?

Odpowiedz

18

Tak, oczywiście metoda apply jest metodą, która przyjmuje wszystkie parametry klas przypadków. To z grubsza przekłada się na następujące kwestie:

implicit val creatureReads = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean] and 
    (__ \ "weight").read[Float] 
)((name: String, isDead: Boolean, weight: Float) => new Creature(name, isDead, weight)) 

dla brakujących pól należy rzeczywiście używać readNullable i owinąć pól klas Option. Jeśli istnieją rozsądne wartości domyślne dla pól opcjonalnych, można zamiast tego użyć orElse(Reads.pure(value)).

Powiedzmy weight jest opcjonalny i isDead jest fałszywe domyślnie:

implicit val creatureReads = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and 
    (__ \ "weight").readNullable[Float] 
)(Creature.apply _) 

Czasami nawet nie chcą czytać coś z JSON. W tym przypadku, jedną z możliwości jest przepuszczenie wartość wyraźnie:

def creatureReads(createdAt: DateTime) = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and 
    (__ \ "weight").readNullable[Float] and 
    (__ \ "createdAt").read(createdAt) 
)(Creature.apply _) 
+0

Dzięki, że nie straciła gola dla mnie. Ale jeszcze jedno pytanie dotyczące JSErrors, jaki byłby czysty sposób określenia niestandardowego błędu zamiast "ścieżka \ foo" nie znaleziono? Czy jest gdzieś, gdzie mogę umieścić w Read? –

+0

Nie dla domyślnych odczytów, ale zależy to od przypadku użycia. Czy możesz z tym podzielić osobne pytanie? –

+0

Oczywiście, czy możesz rzucić okiem na http://stackoverflow.com/questions/17818924/play-framework-json-reader-and-custom-jserrors –

-1

Uważam, że jest to o wiele bardziej czytelny:

implicit val createReads = new Reads[Creature] { 
    override def reads(json: JsValue): JsResult[Creature] = { 
    val creature = Creature(
     name = (json \ "name").as[String], 
     isDead = (json \ "isDead").as[Boolean], 
     weight = (json \ "weight").as[Float] 
    ) 
    JsSuccess(creature) 
    } 
} 
+0

To nie zapewnia przypadków 'JsError', nie? Czy gra automatycznie obsługuje wyjątki wyrzucane w 'reads' i zapewnia im' JsError'? – advait