2012-11-17 17 views
5

Próbuję wysłać dane od klienta do serwera za pomocą żądania JSON. Ciało żądanie JSON wygląda następująco:Obsługa żądań JSON w Play Framework 2.0 Scala

{ 
"upload": 
    { 
    "ok":"some message", 
    "assemblyId":"a9d8f72q3hrq982hf98q3" 
    } 
} 

Play jest w stanie rozpoznać ciało żądania jako JSON, ale gdy próbuję analizować poszczególne wartości, a mianowicie „upload” obiekt, Play narzeka, że ​​nie może znajdź określony parametr.

metoda Scala jest następujący:

def add(course:Long) = withAccount { account => implicit request => 
    println() 
    println(request.body) // output: AnyContentAsJson({"upload":{"ok":"ASSEMBLY_COMP... 

    request.body.asJson.map { json => 
    println() 
    println(json) // output: {"upload":{"ok":"ASSEMBLY_COMPLETED","assemb... 

    (json \ "upload").asOpt[models.SomeClass].map { upload => 
     Ok("Got upload") 
    }.getOrElse { 
     BadRequest("Missing parameter [upload]") 
    } 
    }.getOrElse { 
    BadRequest("Expecting Json data") 
    } 
} 

mam problemy ze zrozumieniem, dlaczego powyższy kod nie powiedzie się. Metoda nie ma problemu z odwzorowaniem treści żądania na obiekt Json. Polecenie "println (json)" wypisuje dokładnie to samo, co Chrome pokazuje mi jako "Request Payload". Jednak gdy próbuję pobrać obiekt główny, "upload", nie działa. A metoda zwraca złe żądanie narzekające na brakujący parametr.

Odpowiedz

4

Aby wykonać jakoOpt [models.SomeClass] musi istnieć instancja Reads, aby działała.

Oto przykład

case class SomeClass(ok: String, assemblyId: String) 
implicit object SomeClassReads extends Reads[SomeClass] { 
    def reads(json: JsValue) = 
    SomeClass((json \ "ok").as[String], (json \ "assemblyId").as[String]) 
} 

można zobaczyć w jaki sposób zaimplementować Czyta instancji w https://github.com/playframework/Play20/blob/2.0.x/framework/src/play/src/main/scala/play/api/libs/json/Reads.scala#L35

+0

Czy różni się to od instancji Format, która ma metody odczytu i zapisu? –

+0

Myślę, że format jest funkcją 2.1? Nie jestem pewien, ale w anycase, potrzebujesz tylko odczyty do deserializacji. –

+0

Mam format z metodami odczytu i zapisu. Kod kompiluje, myślę, że jest problem ze sposobem mapowania żądania json w moim kontrolerze. –

1

Jeśli używasz zabaw 2,1x, odczytuje zmieniła się nieco od 2,0x i to chyba Twój główny problem (jak ja).

Możesz znaleźć bardzo dobre wyjaśnienie here.

prostu ten kod działa poprawnie:

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

case class Person(name: String, age: Int, lovesChocolate: Boolean) 

implicit val personReads = Json.reads[Person] 

wyglądać niesamowite, prawda? Ale są pewne punkty, na które należy zwrócić uwagę:

  • Definicja niejawna powinna znajdować się w kontrolerze. Oczywiście są jeszcze inne sposoby na zrobienie tego.

  • Jeśli Twój model jest w klasie modeli (znajduje się w kontrolerze w powyższym przykładzie), nie powinieneś nazwać swojego obiektu tym samym dla swojej klasy. W tym przypadku to nie działa:

    case class Person(name: String, age: Int, lovesChocolate: Boolean)  
    
    object Person{....} //this won't work 
    

ten sposób mają duże zalety. Gorąco polecam zapoznanie się z blogiem this.

Powiązane problemy