gpt4 book ai didi

json - 隐式范围内的 models.AccountStatus 没有 play.api.libs.json.Format 的实例

转载 作者:行者123 更新时间:2023-12-04 02:04:10 24 4
gpt4 key购买 nike

在隐式范围内,models.AccountStatus 没有可用的 play.api.libs.json.Format 实例。

这是取自 github 页面的代码,仅更改了类名和变量名。

package models

import slick.jdbc.H2Profile._
import play.api.libs.json._

case class Account(id: Long, name: String, category: Int, status:AccountStatus)

object Account {
implicit val accountFormat = Json.format[Account]
}

sealed abstract class AccountStatus(val as:Int)

object AccountStatus{
final case object Draft extends AccountStatus(0)
final case object Active extends AccountStatus(1)
final case object Blocked extends AccountStatus(2)
final case object Defaulter extends AccountStatus(3)

implicit val columnType: BaseColumnType[AccountStatus] = MappedColumnType.base[AccountStatus,Int](AccountStatus.toInt, AccountStatus.fromInt)

private def toInt(as:AccountStatus):Int = as match {
case Draft => 0
case Active => 1
case Blocked => 2
case Defaulter => 3
}

private def fromInt(as: Int): AccountStatus = as match {
case 0 => Draft
case 1 => Active
case 2 => Blocked
case 3 => Defaulter
_ => sys.error("Out of bound AccountStatus Value.")
}
}

https://github.com/playframework/play-scala-slick-example/blob/2.6.x/app/models/Person.scala

最佳答案

因此,需要将此代码添加到 object AccountStatus 中。代码块,因为我们需要使用 fromInt转换 IntAccountStatus .这是 Reads为 AccountStatus 定义:

implicit object AccountStatusReads extends Reads[AccountStatus] {
def reads(jsValue: JsValue): JsResult[AccountStatus] = {
(jsValue \ "as").validate[Int].map(fromInt)
}
}

什么是 Reads ?这只是一个 trait它定义了如何将 JsValue(封装 JSON 值的 Play 类)从 JSON 反序列化为某种类型。该特征只需要实现一种方法,即 reads接收一些 json 并返回 JsResult 的方法某种类型的。所以你可以在上面的代码中看到我们有一个 Reads这将在 JSON 中查找名为 as 的字段并尝试将其读取为整数。然后从那里将其转换为 AccountStatus使用已经定义的 fromInt 方法。因此,例如在 scala 控制台中,您可以这样做:
import play.api.libs.json._ 
// import wherever account status is and the above reader
scala> Json.parse("""{"as":1}""").as[AccountStatus]
res0: AccountStatus = Active

虽然这个阅读器并不完美,主要是因为它没有处理你的代码会给你的超出范围的数字的错误:
scala> Json.parse("""{"as":20}""").as[AccountStatus]
java.lang.RuntimeException: Out of bound AccountStatus Value.
at scala.sys.package$.error(package.scala:27)
at AccountStatus$.fromInt(<console>:42)
at AccountStatusReads$$anonfun$reads$1.apply(<console>:27)
at AccountStatusReads$$anonfun$reads$1.apply(<console>:27)
at play.api.libs.json.JsResult$class.map(JsResult.scala:81)
at play.api.libs.json.JsSuccess.map(JsResult.scala:9)
at AccountStatusReads$.reads(<console>:27)
at play.api.libs.json.JsValue$class.as(JsValue.scala:65)
at play.api.libs.json.JsObject.as(JsValue.scala:166)
... 42 elided

你可以通过制作 Reads 来处理这个问题。处理错误。如果你愿意,我可以告诉你怎么做,但首先是 Format 的另一部分是 Writes . This trait , 不出所料,它与 reads 相似,只是它相反。你正在上课 AccountStatus并创建 JsValue (JSON)。所以,你只需要实现 writes方法。
implicit object AccountStatusWrites extends Writes[AccountStatus] {
def writes(as: AccountStatus): JsValue = {
JsObject(Seq("as" -> JsNumber(as.as)))
}
}

然后这可用于将该类序列化为 JSON,如下所示:
scala> Json.toJson(Draft)
res4: play.api.libs.json.JsValue = {"as":0}

现在,这实际上足以让您的错误消失。为什么?因为 Json.format[Account]正在做我们刚刚为你做的所有工作!但是对于帐户。它可以做到这一点,因为它是一个案例类并且有少于 22 个字段。还有 Account 的每个字段有一种方法可以在 JSON 之间进行转换(通过 ReadsWrites )。您的错误消息显示 Account 无法为其自动创建格式,因为它的一部分(状态字段)没有格式化程序。

现在,你为什么要这样做?因为 AccountStatus不是案例类,所以不能调用 Json.format[AccountStatus]在上面。并且因为它的子类是每个对象,它们没有 unapply为它们定义的方法,因为它们不是案例类。所以你必须向库解释如何序列化和反序列化。

既然您说您是 scala 的新手,我想隐含的概念仍然有些陌生。当你看到编译器提示无法找到它需要的隐式时,我建议你玩弄它/做一些阅读以掌握该怎么做。

奖金回合

所以,你可能真的不想自己做这项工作,有一种方法可以避免必须这样做,所以你可以做 Json.format[AccountStatus] .你看 Json.format使用 applyunapply方法来做它肮脏的工作。在 scala 中,这两种方法是为案例类自动定义的。但是你没有理由不能自己定义它们并免费获得它们给你的一切!

那么, apply 怎么办?和 unapply看起来像类型签名明智?每个类(class)都会改变,但在本例中为 apply应该匹配 Int => AccountStatus (从 int 到 AccountStatus 的函数)。所以它是这样定义的:
def apply(i: Int): AccountStatus = fromInt(i)

和 unapply 与此相反,但它需要返回 Option[Int] ,所以看起来像
def unapply(as: AccountStatus): Option[Int] = Option(as.as)

定义了这两个后,您无需自己定义读取和写入,而只需调用
// this is still inside the AccountStatus object { ... } 
implicit val asFormat = Json.format[AccountStatus]

它将以类似的方式工作。

附言我今天要去旅行,但如果其中一些没有意义,请随时发表任何评论,我会稍后再回复你

关于json - 隐式范围内的 models.AccountStatus 没有 play.api.libs.json.Format 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44849424/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com