2016-05-25 8 views
5

Ich erstelle benutzerdefinierte Json-Reader für Fallklassen, aber es kann keine implizite JsonReader-Typklasse für List [T] finden, die in anderen Fallklassen verwendet wird.spray-json kann JsonReader für Typ Liste nicht finden [T]

Wenn ich DefaultJsonProtocol überprüft habe, hat es bereits implizites Format für Sammlungen;

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) 
    } 
    } 

Hier ist der vereinfachte Code;

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) 
    } 
    } 

} 

Hier sind die Fehler;

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) 
               ^

Antwort

3

denke ich, das Problem mit der Tatsache zusammenhängt, dass die JsonReader für List[T] in DefaultJsonProtocol ist ein RootJsonFormat (kein RootJsonReader), was im Grunde bedeutet, dass Sie es lesen kann und es auch schreiben. Also, wenn Sie versuchen, eine List[Item] zu lesen, wird erwartet, dass Sie auch Item s schreiben können. So könnten Sie stattdessen RootJsonFormat verwenden und eine Ausnahme auslösen, falls Sie versuchen, es zu schreiben (da Sie es nicht unterstützen). Zum Beispiel:

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") 
} 

Wenn Sie kennen eine saubere Lösung sind an denen nur die Leser, lassen Sie mich bitte wissen, weil ich in dieses Problem selbst lief und nichts anderes finden konnte.

+0

Danke für die Antwort. Ich habe es gerade von github issue gelernt. Für die saubere Lösung überprüfe meine Antwort, ich denke nicht, dass es ziemlich sauber ist, aber ich möchte die Schreibmethode nicht immer überschreiben, da wir viele benutzerdefinierte Formatierer haben, es ist ziemlich viel Aufwand, also habe ich ein Basismerkmal dafür erstellt. –

+1

Ich sehe :) Ich hatte dieses Problem vor langer Zeit und ich habe mich irgendwie daran gewöhnt, die (unbenutzte) Schreibmethode zu überschreiben. Vielen Dank. – ale64bit

3

ich diese Einschränkung gelernt haben, kommt von Spray-json:

Spray-json ‚s Typklasse Infrastruktur ist um die (Root) JsonFormat Art bauen, nicht die (Root) JsonReader. Sie müssen also tatsächlich ein "Format" angeben, auch wenn Sie gerade lesen.

Check here.

Problem zu überwinden; Ich habe ein anderes Merkmal erstellt, erweitert RootJsonFormat anstelle von reader und überschreibt Schreibmethode mit im Grunde nicht implementierter Methode.

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