我正在尝试使用play框架将json解析为case类。我的目的是检查json中是否存在特定路径。如果存在,则仅读取该路径上的元素。
这是我的代码
package com.learning.avinash.query
import play.api.libs.json.{JsDefined, JsPath, Json, Reads, Writes, __}
import play.api.libs.functional.syntax._
object ParseJson extends App {
case class Msisdn(primaryId: Option[String], relatedAccountId: Option[String])
object Msisdn {
implicit val readData: Reads[Msisdn] = (
(JsPath \ "primary-id").readNullable[String] ~
(JsPath \ "meta" \ "related-accoount-id").readNullable[String]
) (Msisdn.apply _)
}
val testJson = """{
"resources": [
{
"valid-for-start-datetime": "2019-08-23T10:47:17.485Z",
"primary-id": "393823468684",
"meta": {
"related-account-id": "10001771",
"roles": [
"customer"
]
}
},
{
"valid-for-start-datetime": "2019-08-23T10:47:17.485Z",
"primary-id": "393823467689"
}
]
}"""
println((Json.parse(testJson) \ "resources").as[List[Msisdn]])
}
在第二个对象的资源数组中,您可以观察到此代码完全丢失
"meta": {
"related-account-id": "10001771",
"roles": [
"customer"
]
}
现在,当我尝试解析json时,它失败并且出现以下异常
Exception in thread "main" play.api.libs.json.JsResultException: JsResultException(errors:List(((1)/meta/related-accoount-id,List(JsonValidationError(List(error.path.missing),WrappedArray())))))
正在播放中是否有预定义的功能/方法,以便我可以检查是否此
(JsPath \ "meta")
特定路径存在,然后仅读取该路径中的元素。还是应该编写一个自定义函数来检查路径是否存在。
我可以看到一个期望有Jsvalue的JsDefined()。
https://www.playframework.com/documentation/2.7.x/api/scala/play/api/libs/json/index.html
final case classJsDefined(value: JsValue)
Wrapper for JsValue to represent an existing Json value.
请提供任何想法,想法,帮助或建议。
也许会有所帮助...
import play.api.libs.json._
object ParseJson extends App {
case class Msisdn(`primary-id`: Option[String], meta: Option[Meta])
case class Meta(`related-account-id`: Option[String])
implicit val metaFormat = Json.format[Meta]
implicit val msisdnFormat = Json.format[Msisdn]
输出:List(Msisdn(Some(393823468684),Some(Meta(Some(10001771)))), Msisdn(Some(393823467689),None))
然后您可以使用
case class Msisdn(private val `primary-id`: Option[String],
private val meta: Option[Meta]) {
def primaryId: Option[String] = `primary-id`
def accountId: Option[String] = meta.flatMap(_.`related-account-id`)
}
更改公共API。
还有另一种方法,但是我忘了怎么做。