2013-12-17 10 views
6

Witam Mam problem z parserem treści JSON. Mój problem jest następujący Mam klasę przypadków z niektórymi opcjonalnymi parametrami (opcja [T]) i parametrem z wartością domyślną, której nie chcę, aby został wpisany jako Opcja [T].Zagraj w domyślne pole wartości domyślnej wartości dla Scala JSON

Jednak podczas analizowania ciało JSON mający pole z wartością domyślną pominiętym pojawia się błąd

play.api.libs.JsError 
/count error path missing 

Oto mój kod kontrolera:

object MyController extends Controller{ 


    implicit val itemWrites = Json.writes[Item] 
    implicit val itemReads = Json.reads[Item] 
    implicit val itemFormats = Json.format[Item] 

    def add = DBAction(parse.json){ implicit rs => 

    val item = rs.request.body.validate[Item] 
} 

Oto moja klasa przypadek:

case class Item(id:Option[Int], name:String, description:Option[String], count:Int=0) 

Czy mogę uzyskać takie samo zachowanie jak Opcja [T] z domyślnym polem wartości?

Dzięki

Używam:

  • Scala 2,10
  • play Framework 2.2.1
  • Play-Slick plugin 0.5.0.8

Odpowiedz

4

Prawie. Można określić wartość domyślną z opcją jak ten:

case class Item(description:Option[String] = Some("String")) 

Jeśli zdecydowanie nie chcą opcję, można rzucić okiem tutaj:

Defaults for missing properties in play 2 JSON formats

+0

Witam, dziękuję Wolałbym nie mieć opcji. Jeśli chodzi o podany link. Użytkownik twierdzi, że jego obecne rozwiązanie ma pewne wady i muszę powiedzieć, że się zgadzam. Jeśli jednak nie zaproponuje się lepszego rozwiązania, wykorzystam jego podejście, ponieważ nie widzę sposobu na obejście problemu. – ufasoli

+0

Najlepsze rozwiązanie wymagałoby napisania makra, aby automatycznie utworzyć withDefault, jest to jednak przedsięwzięcie :( – Jean

+0

Tak, to jest spory wysiłek ... – ufasoli

1

Jeden obejście byłoby napisać metoda apply, która przyjmuje domyślną wartość count jako opcję i obsługuje konstrukcję (nie można jej nazwać, ponieważ potrzebujemy jednoznacznej nazwy podczas budowania naszych odczytów):

object Item{ 
    def applyOpt(id:Option[Int], name:String, description:Option[String], count:Option[Int]): Item = count.map{c => 
    Item(id, name, description, c) 
    }.getOrElse{ 
    Item(id, name, description) 
    } 
} 

Następnie można użyć readNullable na wartość domyślną, która będzie przechodzić opcję [Int], aby applyOpt:

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


implicit val itemReads: Reads[Item] = (
    (__ \ "id").readNullable[Int] and 
    (__ \ "name").read[String] and 
    (__ \ "description").readNullable[String] and 
    (__ \ "count").readNullable[Int] 
)(Item.applyOpt _) 

pewnością nie jest idealny, zwłaszcza jeśli masz kilka pól domyślnych, ale szybkie obejście, że unika konieczności radzić sobie z makrami lub refleksją.

+0

tak, ale miałem nadzieję, że nie piszę Czytnika ze wszystkimi polami, ponieważ mam wiele klas przypadków z tym samym scenariuszem, ale więcej pól, które jest żmudne pisać i podatne na błędy, gdy model jeszcze nie jest Stuprocentowo stabilny i musisz go zaktualizować, miałam nadzieję, że to zadziała po prostu tak, jak robi to Jackson w Javie – ufasoli