玩 - 自定义的Json与通用界面污物(Play - Custom Json with Generi

2019-10-21 19:08发布

我有一个CRUD控制器在我的应用程序与JsonInception完美的作品,但不能用自定义JSON转换器。

按照给定的情况下类:

case class Validity(id: Option[UUID], objectType: String, since: DateTime, until: DateTime, objectId: UUID, validityTargetId: UUID, validityTargetType: String)

我有一个对象的同伴如下:

object Validity extends CrudObject[Validity] {
  implicit val reads = Json.reads[Validity]
  implicit val writes = Json.writes[Validity]
}

凡我CrudObject是给定的代码特征:

trait CrudObject[T] {
  val reads: Reads[T]
  val writes: Writes[T]
}

这是必要的,因为我在一个通用界面污物正在工作。 没有这一点,玩的就是无法找到任何隐含的转换器。

所以,我的通用控制器界面污物,是这样的:

trait CrudController[T] extends Controller {

  def service: ServiceModule[T]
  def companion: CrudObject[T]

  def search...
  def insert...

  implicit def reads: Reads[T] = companion.reads
  implicit def writes: Writes[T] = companion.writes

并为每个控制器,我有如下:

object ValidityController extends CrudController[Validity] {
  override def service: GenericServiceModule[Validity] = ServiceModule
  override def companion: CrudObject[Validity] = Validity
}

好吧,这个设计想法,就像我说的,完美的作品,我需要设计一个自定义的JSON转换器。 是的,我知道,这是很简单的事,但正在发生的事情,我不知道如何摆脱这一点。

现在我正在努力做到以下几点:

implicit val reads: Reads[Validity] = (
      (JsPath \ "id").read[String] and
      (JsPath \ "objectType").read[String] and
      (JsPath \ "since").read[Long] and
      (JsPath \ "until").read[Long] and
      (JsPath \ "objectId").read[String] and
      (JsPath \ "validityTargetId").read[String] and
      (JsPath \ "validityTargetType").read[String]
    )(unlift(Validity.apply _))

它给我:

Type mismatch, expected: (NotInferedA) => Option[NotInferedB], actual: (CrudObject[Nothing]) => CrudObject[Nothing]

我相信这是发生的Cuz CrudObject是一个特点,并且不能适用,不应用。

总之,去除CrudObject给了我一个类似的错误:

Type mismatch, expected: (NotInferedA) => Option[NotInferedB], actual: (Option[UUID], String, DateTime, DateTime, UUID, UUID, String) => Validity

但即使我能解决这个问题,我不能没有CrudObject由于我GenericCrud想象的生活。

有什么想法吗?

PS:感谢@mz谁一直给我一些帮助,通过计算器=)

UPDATE

我几乎没有使用这种方法:

implicit object validityFormat extends Format[Validity] {
    override def writes(o: Validity): JsValue = {
      Json.obj(
        "id" -> JsString(o.id.getOrElse(null).toString),
        "objectType" -> JsString(o.objectType),
        "since" -> JsString(o.since.toString),
        "until" -> JsString(o.since.toString),
        "objectId" -> JsString(o.objectId.toString),
        "validityTargetId" -> JsString(o.validityTargetId.toString),
        "validityTargetType" -> JsString(o.validityTargetType))
    }

    override def reads(json: JsValue): JsResult[Validity] = {
      JsSuccess(Validity(
        (json \ "id").as[Option[UUID]],
        (json \ "objectType").as[String],
        (json \ "since").as[DateTime],
        (json \ "until").as[DateTime],
        (json \ "objectId").as[UUID],
        (json \ "validityTargetId").as[UUID],
        (json \ "validityTargetType").as[String])
      )
    }
  }

使用这种方式,这是从不同的文档斯卡拉组合程序 ,我没有得到以前的错误,这是很好的,没有类型不匹配=)

现在我工作了就弄清楚如何转换到UUID和日期时间。

UPDATE

我这样做,工作的例子,但我接受了@mz答案,因为有样板比我少,但都工作得很好。 最大的区别是,在我的方法,我需要的日期时间和UUID提供了一些自定义的转换器,而@mz办法你不知道!

implicit object UUIDFormatter extends Format[UUID] {
    override def reads(json: JsValue): JsResult[UUID] = {
      val uuid = json.validate[String]
      JsSuccess(UUID.fromString(uuid.get))
    }

    override def writes(o: UUID): JsValue = {
      JsString(o.toString)
    }
  }

  implicit object DateTimeFormatter extends Format[DateTime] {
    override def reads(json: JsValue): JsResult[DateTime] = {
      val datetime = json.validate[Long]
      JsSuccess(new DateTime(datetime.get))
    }

    override def writes(o: DateTime): JsValue = {
      JsNumber(o.getMillis)
    }
  }

  implicit object validityFormat extends Format[Validity] {
    override def writes(o: Validity): JsValue = {
      Json.obj(
        "id" -> JsString(o.id.getOrElse(null).toString),
        "objectType" -> JsString(o.objectType),
        "since" -> JsNumber(o.since.getMillis),
        "until" -> JsNumber(o.since.getMillis),
        "objectId" -> JsString(o.objectId.toString),
        "validityTargetId" -> JsString(o.validityTargetId.toString),
        "validityTargetType" -> JsString(o.validityTargetType))
    }

    override def reads(json: JsValue): JsResult[Validity] = {
      JsSuccess(Validity(
        (json \ "id").as[Option[UUID]],
        (json \ "objectType").as[String],
        (json \ "since").as[DateTime],
        (json \ "until").as[DateTime],
        (json \ "objectId").as[UUID],
        (json \ "validityTargetId").as[UUID],
        (json \ "validityTargetType").as[String])
      )
    }

Answer 1:

有几个问题在这里,但他们都不是相关的仿制药,因为你处理的具体类型Validity

首先,使用最后一个参数Reads组合程序应该是(Validity.apply _) 你只用unliftWrites

其次,在组合子的类型必须映射到你的类型的Validity类。

implicit val reads: Reads[Validity] = (
  (JsPath \ "id").readNullable[UUID] and    // readNullable reads to Option
  (JsPath \ "objectType").read[String] and
  (JsPath \ "since").read[DateTime] and
  (JsPath \ "until").read[DateTime] and
  (JsPath \ "objectId").read[UUID] and
  (JsPath \ "validityTargetId").read[UUID] and
  (JsPath \ "validityTargetType").read[String]
)(Validity.apply _)

Reads已经存在UUIDDateTime ,所以这应该工作正常。

同样, Writes[Validity]是这样的:

implicit val writes: Writes[Validity] = (
  (JsPath \ "id").writeNullable[UUID] and
  (JsPath \ "objectType").write[String] and
  (JsPath \ "since").write[DateTime] and
  (JsPath \ "until").write[DateTime] and
  (JsPath \ "objectId").write[UUID] and
  (JsPath \ "validityTargetId").write[UUID] and
  (JsPath \ "validityTargetType").write[String]
)(unlift(Validity.unapply))


Answer 2:

你好我认为你的情况类有您的读取必须readnullable在可选参数必须是这样的一个选项参数,我不知道有UIID和字符串

case class Validity(id: Option[UUID], objectType: String, since: DateTime, until: DateTime, objectId: UUID, validityTargetId: UUID, validityTargetType: String)

implicit val reads: Reads[Validity] = (
      (JsPath \ "id").readNullable[UIID] and
      (JsPath \ "objectType").read[String] and
      (JsPath \ "since").read[Long] and
      (JsPath \ "until").read[Long] and
      (JsPath \ "objectId").read[String] and
      (JsPath \ "validityTargetId").read[String] and
      (JsPath \ "validityTargetType").read[String]
    )(unlift(Validity.apply _))


文章来源: Play - Custom Json with Generic Crud