【问题标题】:Scala reads object with nested optional propertyScala 读取具有嵌套可选属性的对象
【发布时间】:2017-11-26 00:26:51
【问题描述】:

我正在尝试为以下课程写一篇文章

case class User(id: String, imageId: Option[String])

我拥有的 JSON 如下所示:

{
  "id": 1
  "image": { "id" : 2 }
}

但是“图像”字段可能不存在,或者它可能为空。 我的阅读是这样的:

implicit val userReader: Reads[User] = (
 (JsPath \ "id").read[String] and
 (JsPath \ "image" \ "id").readNullable[String]
) (User.apply _)

但这似乎不起作用,当它找到没有图像的样本时,我仍然会收到错误消息。 'ValidationError [...] error.path.missing [...] /image/id'

如何解决?我不想创建一个我不会在任何地方使用的 Image 类。

【问题讨论】:

    标签: json scala playframework-2.0


    【解决方案1】:

    我认为问题在于您尝试读取 StringidInt。您应该注意您的 json / reader 中的类型。

    两种选择

    • 如果id 真的是Int,则将其读作Int
    • 如果idString,请更改您的JSON

    如果您仍想在您的案例课程中使用String,您可以这样做:

    (JsPath \ "image" \ "id").readNullable[Int].map(_.toString)
    

    【讨论】:

    • 这显然是个问题,但它并没有抱怨,因为我尝试了一个没有图像的示例,所以它看不到类型不匹配。我把它换成String了,还是一样的错误。
    • 同样适用于根目录下的id
    【解决方案2】:

    您忘记了两个元素("id""image")之间的逗号。这就是解析器似乎缺少 /image/id 路径的原因。

    有各种各样的工具可以验证 JSON 结构,例如 https://jsonlint.com/ 。 所以你的 JSON 结构应该是这样的:

    {
        "id": 1,
        "image": {
            "id": 2
        }
    }
    

    【讨论】:

      【解决方案3】:

      我可能会迟到,但这里有一个解决方法:

      implicit val userReader: Reads[User] = (
          (JsPath \ "id").read[String] and
          (JsPath \ "image" \ "id").readNullable[String].orElse((__ \ "dummy").readNullable[String])
      ) (User.apply _)
      

      不完美,但效果很好

      更好的解决方案是直接将 Js Reads(JsSuccess(None:Option[Int])) 投射到 orElse 中,但我无法做到...

      【讨论】:

        猜你喜欢
        • 2017-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-30
        • 2021-03-08
        • 2021-05-24
        • 1970-01-01
        相关资源
        最近更新 更多