【问题标题】:Using JSON Implicit Reader使用 JSON 隐式阅读器
【发布时间】:2014-04-01 14:32:28
【问题描述】:

我有一个从 MongoDB 返回的 List[play.api.libs.json.JsObject] 具有以下文档架构:

{
  "web_category_id" : "blah",
  "web_category_name" : "abcabc",
  "top_group_id" : "blah",
  "top_group_name" : "namehere",
  "sub_web_category" : [
    {
      "name" : "blah",
      "id" : "idblah"
    },
            {
      "name" : "another blah",
      "id" : "another idblah"
    } 

  ]

}

我正在尝试使用隐式读取器将数据读入 WebCategory 案例类:

case class WebCategory(topGroupName: String,
                       topGroupID: String,
                       webCategoryName : String,
                       webCategoryID : String,
                       subWebCats:Seq[SubWebCat])

case class SubWebCat(name:String, id:String)

到目前为止,我的代码(距离编译一百万英里)是:

implicit val webCategoryReader = (
  (__/ "top_group_name").read[String] and
  (__/ "top_group_id").read[String] and
  (__/ "web_category_name").read[String] and
  (__/ "web_category_id").read[String] and
  (__/ "sub_web_category").read[List[Map[String, String]].map("name", "id"))
)(WebCategory)

我什至不知道是否可以构建一个包含另一个案例类作为其值之一的案例类。

非常感谢您的帮助,谢谢!

编辑:

好的,事实证明我在 SubWebCategory 上定义了一个空白的伴随对象(出于我以外的原因)干扰了读者。可能是因为在覆盖的伴随对象中没有应用函数。有人愿意确认吗?

另外,我很昏暗,WebCategory 实际上被定义为:

case class WebCategory(topGroupName: String,
                   topGroupID: String,
                   webCategoryName : String,
                   webCategoryID : String,
                   subWebCats:Option[Seq[SubWebCat]])

所以上面特拉维斯布朗提供的答案应该是(我的错,不是他的!):

implicit val webCategoryReader: Reads[WebCategory] = (
  (__ \ "top_group_name").read[String] and
  (__ \ 'top_group_id).read[String] and
  (__ \ 'web_category_name).read[String] and
  (__ \ 'web_category_id).read[String] and
  (__ \ 'sub_web_category).read[Option[List[SubWebCat]]]
    )(WebCategory)

感谢您的帮助,特拉维斯

【问题讨论】:

  • 除了给出的答案之外,您可能还想看看my answer here,它显示了嵌套案例类 JSON 转换的完整工作示例。

标签: scala playframework-2.1


【解决方案1】:

实际上,您已经非常接近了——您只需要进行一些小改动。首先,您可以使用嵌套案例类,但您需要为每个案例类提供Reads 实例。我将从内部开始:

implicit val subWebCatReader: Reads[SubWebCat] = (
  (__ \ 'name).read[String] and (__ \ 'id).read[String]
)(SubWebCat)

请注意,我在路径中使用符号而不是字符串;这完全是个人喜好问题(不过,保持一致总是好的)。还要注意斜线的方向——它们应该是向后的,而不是向前的。

我们可以将这些更改应用到您的代码并进行一次额外的编辑(对读取子类别字段的部分),我们就完成了:

implicit val webCategoryReader: Reads[WebCategory] = (
  (__ \ "top_group_name").read[String] and
  (__ \ 'top_group_id).read[String] and
  (__ \ 'web_category_name).read[String] and
  (__ \ 'web_category_id).read[String] and
  (__ \ 'sub_web_category).read[List[SubWebCat]]
)(WebCategory)

我们知道如何阅读SubWebCat,所以我们也知道如何阅读List[SubWebCat]——无需查看地图。

【讨论】:

  • 谢谢,我完全按照你写的那样做,但是我的 IDE 在最​​后的 (SubWebCat) 和 (WebCategory) 下都收到一个错误:“应用程序不接受参数”。还有一个编译错误: (yada yada)...不能应用于 (models.Products.WebCategory.type) (__ \ "web_category_id").read[String] 和
  • 这很奇怪。您是否定义了自己的WebCategory 等对象?你可以尝试添加.apply——即)(WebCategory.apply)?
  • 确切的编译错误是:[B(in method apply)(in method apply)(in method apply)(in method apply)(in method apply)(in method apply)(in method apply )(在方法应用中)](f: (String, String, String, String, List[models.Products.SubWebCategory]) => B(在方法应用中)(在方法应用中)(在方法应用中)(在方法应用中)(在方法应用中)(在方法应用中)(在方法应用中)(在方法应用中))(隐式fu: play.api.libs.functional.Functor[play.api.libs.json.Reads])
  • ...play.api.libs.json.Reads[B(in method apply)(in method apply)(in method apply)(in method apply)(in method apply)(in method apply)(in method apply)(in method apply)] 不能应用于 (models.Products.WebCategory.type) (__ \ 'web_category_id).read[String] 和
  • 是的,我已经在同一个文件中定义了 WebCategory 和 SubWebcategory 案例类和伴随对象作为隐式..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多