gpt4 book ai didi

json - Play JSON : reading optional nested properties

转载 作者:行者123 更新时间:2023-12-05 01:13:07 26 4
gpt4 key购买 nike

我有以下案例类和 JSON 组合器:

case class Commit(
sha: String,
username: String,
message: String
)

object Commit {
implicit val format = Json.format[Commit]
}

case class Build(
projectName: String,
parentNumber: String,
commits: List[Commit]
)

val buildReads: Reads[Build] =
for {
projectName <- (__ \ "buildType" \ "projectName").read[String]
name <- (__ \ "buildType" \ "name").read[String]
parentNumber <- ((__ \ "artifact-dependencies" \ "build")(0) \ "number").read[String]
changes <- (__ \ "changes" \ "change").read[List[Map[String, String]]]
} yield {
val commits = for {
change <- changes
sha <- change.get("version")
username <- change.get("username")
comment <- change.get("comment")
} yield Commit(sha, username, comment)
Build(s"$projectName::$name", parentNumber, commits)
}

我的 Build 的 JSON 读取组合器将处理传入的 JSON,例如:

{
"buildType": {
"projectName": "foo",
"name": "bar"
},
"artifact-dependencies": {
"build": [{
"number": "1"
}]
},
"changes": {
"change": [{
"verison": "1",
"username": "bob",
"comment": "foo"
}]
}
}

但是,如果缺少artifact-dependencies,它就会崩溃。我希望这是可选的。

我应该使用 readNullable 吗?我曾尝试这样做,但失败了,因为它是一个嵌套属性。

这看起来实用吗,还是我在滥用 JSON 组合器将我的 JSON 解析为案例类?

最佳答案

目前未使用其伴随对象中的 Format[Commit]。我们没有理由不能为此使用简单的组合器并分离逻辑。

case class Commit(sha: String, username: String, message: String)

object Commit {

implicit val reads: Reads[Commit] = (
(__ \ "version").read[String] and
(__ \ "username").read[String] and
(__ \ "comment").read[String]
)(Commit.apply _)

}

然后,如果 "artifact-dependencies" 可以丢失,我们应该在 Build 中将 parentNumber 设为 Option[String] .

 case class Build(projectName: String, parentNumber: Option[String], commits: List[Commit])

我将合并项目名称的 Reads 拆分为一个单独的,以使 Reads[Build] 看起来更干净一些。

val nameReads: Reads[String] = for {
projectName <- (__ \ "projectName").read[String]
name <- (__ \ "name").read[String]
} yield s"$projectName::$name"

然后,当缺少"artifact-dependencies"时,我们可以使用orElseReads.pure(None)来填充它当整个分支(或子分支)不存在时使用 None。在这种情况下,这比映射每个步骤要简单。

implicit val buildReads: Reads[Build] = (
(__ \ "buildType").read[String](nameReads) and
((__ \ "artifact-dependencies" \ "build")(0) \ "number").readNullable[String].orElse(Reads.pure(None)) and
(__ \ "changes" \ "change").read[List[Commit]]
)(Build.apply _)

val js2 = Json.parse("""
{
"buildType": {
"projectName": "foo",
"name": "bar"
},
"changes": {
"change": [{
"version": "1",
"username": "bob",
"comment": "foo"
}]
}
}
""")

scala> js2.validate[Build]
res6: play.api.libs.json.JsResult[Build] = JsSuccess(Build(foo::bar,None,List(Commit(1,bob,foo))),)

关于json - Play JSON : reading optional nested properties,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31769650/

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