spray / spray-json

A lightweight, clean and simple JSON implementation in Scala
Apache License 2.0
972 stars 190 forks source link

implicit diverge for nested parametrized case classes #176

Open MasseGuillaume opened 8 years ago

MasseGuillaume commented 8 years ago

I'm working on parsing elasticsearch results:

import spray.json._

// out model
case class Bob(name: String)

// elasticsearch domain
case class Hit[T](score: Double, source: T)
case class SearchResult[T](hits: Seq[Hit[T]])

object Protocol extends DefaultJsonProtocol {
  implicit val bobFormat = jsonFormat1(Bob)

  implicit def hitFormat[T: JsonFormat] = new RootJsonFormat[Hit[T]] {
    def write(hit: Hit[T]) = JsObject("_score" -> JsNumber(hit.score), "_source" -> hit.source.toJson)
    def read(value: JsValue) = 
      value.asJsObject.getFields("_score", "_source") match {
        case Seq(JsNumber(score), source) => Hit(score.toDouble, source.convertTo[T])
        case _ => deserializationError("expected hit")
      }
  }
  implicit def searchResultsFormat[T: JsonFormat](results: SearchResult[T]) = new RootJsonFormat[SearchResult[T]] {
    def write(result: SearchResult[T]) = JsObject("_hits" -> result.hits.toJson)
    def read(value: JsValue) =
      value.asJsObject.getFields("_hits") match {
        case Seq(hits) => SearchResult(hits.convertTo[Seq[Hit[T]]])
        case _ => deserializationError("expected hits")
      }
  }
}
import Protocol._

val json = 
"""
{
  "_hits": [
    {
      "_score": 1.0,
      "_source": {
        "name": "woot"
      }
    }
  ]
}
""".parseJson.asJsObject

json.convertTo[SearchResult[Bob]]

//Cannot find JsonReader or JsonFormat type class for SearchResult[Bob]
// ^not enough arguments for method convertTo: (implicit evidence$1: spray.json.JsonReader[SearchResult[Bob]])SearchResult[Bob].
// Unspecified value parameter evidence$1.