2013-06-25 13 views
6

Sto utilizzando Play Framework 2.1 e Scala 2.10.1 e vorrei creare una funzione generale per costruire un JsArray da un elenco di case case personalizzate.Tipo di differimento Scala

private def buildJsArray[T](l: List[T])(result: JsArray): JsArray = { 
    l match { 
     case List() => result 
     case x::xs => buildJsArray(xs)(result :+ Json.toJson(x)) // compiling error here! 
    } 
    } 

utilizzo:

val applyJsonArray = buildJsArray(List[Apple])(new JsArray()) 

Tuttavia, un errore di compilazione è gettato:

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

ho un deserializzatore JSON scritto per la particolare classe caso (vale a dire, Case class di Apple).

Come si differisce il compilatore per verificare il tipo di x in fase di esecuzione anziché in fase di compilazione?

Grazie mille!

risposta

15

Come riparare un errore di

È necessario aggiungere un implicit parameter al metodo come questo:

def buildJsArray[T](l: List[T])(result: JsArray)(implicit tjs: Writes[T]): JsArray 

C'è una tale parametro nel metodo Json.toJson.

Il motivo per cui è necessario aggiungere questo parametro è che si sa come convertire T in json solo quando si conosce che cos'è T. Significa che hai il metodo per serializzare T solo quando chiami buildJsArray e questo parametro ti consente di passare questo metodo di serializzazione al metodo buildJsArray.

Come costruire un JSArray

si potrebbe utilizzare un costruttore di JsArray. Ci vuole un Seq[JsValue]:

new JsArray(l.map{Json.toJson(_)}) 

C'è già un implicit Writes per Traversable quindi non è necessario un proprio metodo buildJsArray, si può solo metodo Json.toJson utilizzare con il parametro di tipo List[T].

aggiunta

Si dovrebbe dare un'occhiata alla collezione api. Esso consente di scrivere codice più leggibile e più breve:

def buildJsArray[T](l: List[T])(implicit tjs: Writes[T]): JsArray = 
    l.foldLeft(new JsArray){ (r, x) => r :+ Json.toJson(x) } 
+0

risposta perfetta, nulla da aggiungere :) –

+0

Quando si tratta di JSObject (s), non è possibile utilizzare il tipo di OFormat generico per il vostro implicito. Dovrai eseguire una implicita per OWrite e una per Letture – JMess