【问题标题】:unable to create an implicit read for JSON无法为 JSON 创建隐式读取
【发布时间】:2018-04-25 20:09:32
【问题描述】:

我的服务器代码将收到以下JSON

{
    "signin-info":{
        "email" : "someemail",
        "password": "password"
    }
}

我创建了以下 2 个案例类来表示这种结构。

case class UserSigninInfo(
  email:String,
  password:String
)
case class UserSignin(
  signinInfo: UserSigninInfo
)

为了读取 JSON,我创建了以下 2 个Reads

  implicit val userSigninInfoReads:Reads[UserSigninInfo] = (
    (JsPath \ "email").read[String] and
    (JsPath \ "password").read[String]
  )(UserSigninInfo.apply _)

  implicit val userSigninReads:Reads[UserSignin] = (
    (JsPath \ "signin-info").read[UserSigninInfo]
  )(UserSignin.apply _)

但是对于userSigninReads,我收到以下编译错误。我做错了什么?

overloaded method value read with alternatives:
[error]   (t: models.UserSigninInfo)play.api.libs.json.Reads[models.UserSigninInfo] <and>
[error]   (implicit r: play.api.libs.json.Reads[models.UserSigninInfo])play.api.libs.json.Reads[models.UserSigninInfo]
[error]  cannot be applied to (models.UserSigninInfo => models.UserSignin)
[error]     (JsPath \ "signin-info").read[UserSigninInfo]
[error]                                 `

【问题讨论】:

    标签: scala playframework-2.6


    【解决方案1】:

    为您的主要对象构造读取的解决方案是:

    implicit val userSigninReads : Reads[UserSignin] =
      (JsPath \ "signin-info").read[UserSigninInfo].map(UserSignin(_))
    

    这是因为它只有一个字段。

    你的结构本质上是:

    ((JsPath \ "signin-info").read[UserSigninInfo])(UserSignin.apply _)
    

    这很简单

    (JsPath \ "signin-info").read[UserSigninInfo](UserSignin.apply _)
    

    因为它只是增加了额外的()

    read 方法确实有两种选择:

    def read[T](t: T) = Reads.pure(t)
    def read[T](implicit r: Reads[T]): Reads[T] = Reads.at[T](this)(r)
    

    它需要隐式读取或显式值,但您正在传递一个函数,这就是编译器抱怨的原因。

    当您将多个字段与and 组合时,会创建不同的对象,例如FunctionalBuilder[M]#CanBuild2[A, B] 为 2 个元素,它有 apply 方法来构造最终的 Reads 实例。

    由于您只有一个对象,您可以通过从所需路径读取UserSigninInfo 并将结果放入UserSigninmap 来创建您的Reads

    【讨论】:

    • 谢谢。我会检查一下。如果我添加另一个字段并使用and,我确实观察到代码有效。虽然我无法理解其中的逻辑。期待您的进一步解释
    • 谢谢。有效。所以(JsPath \ "signin-info").read[UserSigninInfo] 返回Reads[UserSigninInfo]Readsmap 返回一个 UserSigninInfo 类型的对象,该对象被传递给 UserSignin(即 Reads[UserSigninInfo].map(x:UserSigninInfo=&gt;UserSigninInfo.apply(s))?
    • 我不会完全使用这些词,但几乎可以(除了我猜你上一个 sn-p 中的错字,apply 部分中不应该有信息)。 map 是一个函数,可以在给定A =&gt; B 的情况下将Reads[A] 转换为Reads[B]。所以 map 需要一个函数UserSigninInfo =&gt; UserSigninmap 允许我们获得 UserSigninInfo 对象,以便我们可以将其包装到 UserSignin 中,从而产生 Reads[UserSignin]。
    猜你喜欢
    • 2021-10-28
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    相关资源
    最近更新 更多