2016-05-25 23 views
5

Sto creando lettori JSON personalizzati per le classi del caso ma non è possibile trovare la classe di tipo JsonReader implicita per List [T], che viene utilizzata in altri casi.spray-json non riesce a trovare JsonReader per il tipo Elenco [T]

Quando ho controllato DefaultJsonProtocol, ha già il formato implicito per le raccolte;

implicit def listFormat[T :JsonFormat] = new RootJsonFormat[List[T]] { 
    def write(list: List[T]) = JsArray(list.map(_.toJson).toVector) 
    def read(value: JsValue): List[T] = value match { 
     case JsArray(elements) => elements.map(_.convertTo[T])(collection.breakOut) 
     case x => deserializationError("Expected List as JsArray, but got " + x) 
    } 
    } 

Ecco il codice semplificato;

case class Test(i: Int, d: Double) 
case class ListOfTest(t: List[Test]) 

trait TestResultFormat extends DefaultJsonProtocol { 

    import CustomFormat._ 

    implicit object TestJsonFormat extends RootJsonReader[Test] { 

    override def read(json: JsValue): Test = { 

     val jsObject = json.asJsObject 
     val jsFields = jsObject.fields 

     val i = jsFields.get("i").map(_.convertTo[Int]).getOrElse(0) 
     val d = jsFields.get("d").map(_.convertTo[Double]).getOrElse(0d) 

     Test(i, d) 
    } 
    } 

    implicit object ListOfTestJsonFormat extends RootJsonReader[ListOfTest] { 

    override def read(json: JsValue): ListOfTest = { 

     val jsObject = json.asJsObject 
     val jsFields = jsObject.fields 

     val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty) 

     ListOfTest(tests) 
    } 
    } 

} 

Ecco gli errori;

Error:(230, 53) not enough arguments for method convertTo: (implicit evidence$1: spray.json.JsonReader[List[com.xx.Test]])List[com.xx.Test]. 
Unspecified value parameter evidence$1. 
     val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty) 
                ^
Error:(230, 53) Cannot find JsonReader or JsonFormat type class for List[com.xx.Test] 
     val tests = jsFields.get("hs").map(_.convertTo[List[Test]]).getOrElse(List.empty) 
               ^

risposta

3

Credo che il problema è legato al fatto che la JsonReader per List[T] in DefaultJsonProtocol è una RootJsonFormat (non un RootJsonReader), il che significa in pratica si può leggere e anche scrivere. Quindi, quando provi a leggere un List[Item], è previsto che tu sia anche in grado di scrivere Item s. Quindi, è possibile utilizzare RootJsonFormat e generare un'eccezione nel caso si provi a scriverlo (poiché non lo si supporta). Per esempio:

import spray.json._ 

implicit object TestJsonFormat extends RootJsonFormat[Test] { 

    override def read(json: JsValue): Test = { 

    val jsObject = json.asJsObject 
    val jsFields = jsObject.fields 

    val i = jsFields.get("i").map(_.convertTo[Int]).getOrElse(0) 
    val d = jsFields.get("d").map(_.convertTo[Double]).getOrElse(0d) 

    Test(i, d) 
    } 

    override def write(obj: Test): JsValue = serializationError("not supported") 
} 

Se siete a conoscenza di una soluzione pulita che coinvolge solo i lettori, si prega fatemi sapere perché mi sono imbattuto in questo problema me stesso e non poteva trovare niente altro.

+0

Grazie per la risposta. L'ho appena imparato dal problema github. Per la soluzione pulita controlla la mia risposta, non penso che sia abbastanza pulita, ma non voglio sovrascrivere il metodo di scrittura sempre perché abbiamo molti formattatori personalizzati, è piuttosto sovraccarico, quindi ho creato un tratto base per farlo. –

+1

Vedo :) Ho avuto questo problema molto tempo fa e mi sono abituato a scavalcare il metodo di scrittura (inutilizzato). Grazie. – ale64bit

3

Ho imparato che la limitazione viene da spray-JSON:

spray JSON tipo di infrastruttura di classe s' è costruito intorno al tipo (Root) JsonFormat, non il (Root) JsonReader. Quindi dovrai davvero fornire un "formato" anche se stai leggendo.

Check here.

Per superare problema; Ho creato un altro tratto estende RootJsonFormat al posto del lettore e sovrascrive il metodo di scrittura con metodo fondamentalmente non implementato.

trait EmptyWriterFormat[T] extends RootJsonFormat[T] { 
    override def write(o: T): JsValue = ??? 
}