2016-05-25 14 views
5

Tworzę niestandardowe json-czytelniki dla klas case, ale nie można znaleźć ukrytej klasy typów JsonReader dla List [T], która jest używana w innej klasie case.spray-json nie może znaleźć JsonReadera dla typu List [T]

Po sprawdzeniu DefaultJsonProtocol ma on domyślny format dla kolekcji już;

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

Oto uproszczony kod;

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

} 

Tutaj są błędy;

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

Odpowiedz

3

Myślę, że problem jest związany z faktem, że dla List[T]JsonReader w DefaultJsonProtocol jest RootJsonFormat (nie RootJsonReader), co w zasadzie oznacza, że ​​można ją przeczytać, a także pisać. Tak więc, kiedy próbujesz przeczytać List[Item], oczekuje się, że jesteś w stanie napisać s. Item. Więc zamiast tego możesz użyć RootJsonFormat i wyrzucić wyjątek na wypadek, gdybyś spróbował go napisać (ponieważ go nie obsługuje). Na przykład:

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

Jeśli jesteś świadomy czystym roztworze obejmującym tylko czytelników, proszę dać mi znać, bo wpadłem na ten problem samodzielnie i nie mogłem znaleźć nic innego.

+0

Dzięki za odpowiedź. Właśnie dowiedziałem się o tym od kwestii github. Dla czystego rozwiązania sprawdź moją odpowiedź, nie sądzę, że jest całkiem czysta, ale nie chcę przesłonić metody zapisu zawsze, ponieważ mamy wiele niestandardowych formaterów, jest to dość napięte, więc stworzyłem podstawową cechę, aby to zrobić. –

+1

Widzę :) Miałem ten problem dawno temu i przyzwyczaiłem się do przesłonięcia (nieużywanej) metody zapisu. Dzięki. – ale64bit

3

Dowiedziałem się, że ograniczenie pochodzi z natryskowego json:

sprayu-json „s infrastruktura klasa typ jest budować wokół typu (root) JsonFormat, a nie (root) JsonReader. Musisz więc podać "Format", nawet jeśli tylko czytasz.

Check here.

celu przezwyciężenia problemu; Stworzyłem kolejną cechę, która rozszerza RootJsonFormat zamiast czytnika i nadpisuje metodę zapisu w zasadzie nie zaimplementowaną.

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