3 json scala combinators playframework
我有以下case类和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)
}
Run Code Online (Sandbox Code Playgroud)
我的JSON读取combinator Build将处理传入的JSON,例如:
{
"buildType": {
"projectName": "foo",
"name": "bar"
},
"artifact-dependencies": {
"build": [{
"number": "1"
}]
},
"changes": {
"change": [{
"verison": "1",
"username": "bob",
"comment": "foo"
}]
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果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 _)
}
Run Code Online (Sandbox Code Playgroud)
然后,如果"artifact-dependencies"可能会缺失,我们应该让parentNumber一个Option[String]在Build.
case class Build(projectName: String, parentNumber: Option[String], commits: List[Commit])
Run Code Online (Sandbox Code Playgroud)
我Reads将项目名称组合成一个单独的项目,以使Reads[Build]外观更加干净.
val nameReads: Reads[String] = for {
projectName <- (__ \ "projectName").read[String]
name <- (__ \ "name").read[String]
} yield s"$projectName::$name"
Run Code Online (Sandbox Code Playgroud)
然后,对于"artifact-dependencies"缺失的时间,我们可以使用orElse并Reads.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))),)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2160 次 |
| 最近记录: |