Unable to convert generic case class to json using “writes”

萝らか妹 提交于 2019-12-04 08:38:05

问题


I have a class which I want to be able to convert to json:

case class Page[T](items: Seq[T], pageIndex: Int, pageSize: Int, totalCount: Long)

object Page {

  implicit val jsonWriter: Writes[Page[_]] = Json.writes[Page[_]]
}

The error is No apply function found matching unapply parameters


回答1:


You can define Format[Page[T]] for generic case class Page[T] like this:

import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit def pageFormat[T: Format]: Format[Page[T]] =
  ((__ \ "items").format[Seq[T]] ~
    (__ \ "pageIndex").format[Int] ~
    (__ \ "pageSize").format[Int] ~
    (__ \ "totalCount").format[Long])(Page.apply, unlift(Page.unapply))

Although this solution requires more typing, it keeps your case class Page[T] clear of implicit parameter list or need to define concrete subclasses of Page[T].




回答2:


I'd prefer this solution with trait, but in case you do want to make your case class generic you could use one of 2 approaches.

In case you don't have to use Page[_], i.e. you'll always call toJson on Page[Int] or Seq[Page[String]], but not on Page[_] or Seq[Page[_]]:

object Page {
  implicit def pageWriter[T: Writes](): Writes[Page[T]] = Json.writes[Page[T]]
}

In case you have to serialize Page[_]:

case class Page[T](items: Seq[T],
                   pageIndex: Int,
                   pageSize: Int,
                   totalCount: Long)(
      implicit val tWrites: Writes[T])

object Page {
  implicit def pageWriter[T]: Writes[Page[T]] = new Writes[Page[T]] {
    def writes(o: Page[T]): JsValue = {
      implicit val tWrites = o.tWrites
      val writes = Json.writes[Page[T]]
      writes.writes(o)
    }
  }
}



回答3:


I don't think that you can have a generic writer for any type parameter. I propose following:

trait Page[T] {
  val items: Seq[T]
  val pageIndex: Int
  val pageSize: Int
  val totalCount: Long
}

case class IntPage(items: Seq[Int], pageIndex: Int, pageSize: Int, totalCount: Long) extends Page[Int]

object Page {
  implicit def jsonWriter = Json.writes[IntPage]
}



回答4:


maybe you can write something like:

    case class Page(items: JsValue, pageIndex: Int, pageSize: Int, totalCount: Long)

Put the JsValue instead of the Seq[T]

here is my code example:

    case class ResponseObject(state:Int = 1,data:JsValue)

    case class City(id:Int,name:String,sort:String){
      require(id > 0)
    }

      def list = Action {
        implicit val cityFormat:Format[City] = Json.format[City]
        implicit val responseFormat=Json.format[ResponseObject]
        Ok(Json.toJson(ResponseObject(data=Json.toJson(City.list)))).as("application/json")
      }


来源:https://stackoverflow.com/questions/21374060/unable-to-convert-generic-case-class-to-json-using-writes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!