播放具有泛型类的案例类的JSON格式化程序

问题描述 投票:0回答:2

试图为这个案例类编写一个json格式化程序

case class OptionRange[+T](start: Option[T], end: Option[T])

这就是我到目前为止所拥有的

implicit def fmt[T <: OptionRange[_]](implicit fmt: Format[Option[T]]): Format[OptionRange[T]] = new Format[OptionRange[T]] {
  def reads(json: JsValue): JsSuccess[OptionRange[T]] = JsSuccess(new OptionRange[T] (
    (json \ "start").as[Option[T]],
    (json \ "end").as[Option[T]]
  ))
  def writes(i: OptionRange[T]) = JsObject(Seq(
    "start" -> Json.toJson(i.start),
    "end" -> Json.toJson(i.end)
  ))
}

这段代码编译,但当我尝试格式化OptionRange[Int]时,我得到一个错误,没有隐式格式可用。

如何编写隐式范围内可用的格式?

json scala playframework playframework-2.4
2个回答
2
投票

你有一些循环类型的定义。

在我看来,你打算在这种情况下将T评估为Int。但是,在函数定义中,您已经约束了[T <: OptionRange[_]]。因此,Scala认为T必须是某种东西的OptionRange

当你转到函数(implicit fmt: Format[Option[T]])的隐含参数时,这会变得更加复杂。如果TOptionRange[_],那么你告诉编译器需要一个Format[Option[OptionRange[_]]]而不是Format[Option[_]]。您的函数不能成为Format的来源,因为无法对其进行求值以提供隐含的必需。

解决方案是停止约束T

implicit def fmt[T](implicit fmt: Format[Option[T]]) ...

然后,当您尝试将OptionRange格式化为json时:

scala> import play.api.libs.json._
import play.api.libs.json._

scala> case class OptionRange[+T](start: Option[T], end: Option[T])
defined class OptionRange

scala> implicit def fmt[T](implicit fmt: Format[Option[T]]): Format[OptionRange[T]] = new Format[OptionRange[T]] {
     |   def reads(json: JsValue): JsSuccess[OptionRange[T]] = JsSuccess(new OptionRange[T] (
     |     (json \ "start").as[Option[T]],
     |     (json \ "end").as[Option[T]]
     |   ))
     |   def writes(i: OptionRange[T]) = JsObject(Seq(
     |     "start" -> Json.toJson(i.start),
     |     "end" -> Json.toJson(i.end)
     |   ))
     | }
fmt: [T](implicit fmt: play.api.libs.json.Format[Option[T]])play.api.libs.json.Format[OptionRange[T]]

scala> Json.toJson(OptionRange(Some(1), Some(2)))
res0: play.api.libs.json.JsValue = {"start":1,"end":2}

1
投票

这是使用play-framework 2.3.9,Scala 2.11.8执行此操作的方法:

import play.api.libs.json._ // JSON library
import play.api.libs.json.Reads._ // Custom validation helpers
import play.api.libs.functional.syntax._ // Combinator syntax

case class OptionRange[+T](start: Option[T], end: Option[T])

object Hello extends App {

  implicit def formatOptionRange[T](implicit formatT: Format[T]): Format[OptionRange[T]] = 
    (
      (JsPath \ "start").formatNullable[T] and
      (JsPath \ "end").formatNullable[T]
    )(OptionRange.apply, unlift(OptionRange.unapply))

    println(Json.toJson(OptionRange(Some(1), Some(2))))
}

//Prints:
//{"start":1,"end":2}

这是关于format的文档。

© www.soinside.com 2019 - 2024. All rights reserved.