无法使用 JSON Macro Inception 将嵌套 JSON 结构转换为 Scala case class 对象
Not able to use JSON Macro Inception to convert nested JSON structure to Scala case class object
我有一个要求,传入的 JSON 对象很复杂,而且大多是嵌套的
例如:
"users": {
"utype": "PERSON",
"language":"en_FR",
"credentials": [
{
"handle": "xyz@abc.com",
"password": "123456",
"handle_type": "EMAIL"
}
],
"person_details": {
"primary": "true",
"names": [
{
"name_type": "OFFICIAL",
"title": "MR",
"given": "abc",
"family": "zat",
"middle": "pqs",
"suffix":"anathan"
}
],
"addresses": [
{
"ad_type": "HOME",
"line1": "Residential 2211 North 1st Street",
"line2": "Bldg 17",
"city": "test",
"county": "Shefield",
"state" : "NY",
"country_code": "xx",
"postal_code": "95131"
}
]
}
}
为了解析这个结构,我使用下面的案例 类
case class PersonUser (
user_type:String,
language_code:String,
credentials:List[Credential],
person_details:PersonDetails
)
case class Credential(handle:String, password:String,handle_type:String)
case class PersonDetails(
primary_user:Boolean,
names: List[Name],
addresses:List[Address]
)
case class Name(
name_type: String,
title: String,
given: String,
family: String,
middle: String,
suffix:String
)
case class Address(
address_type: String,
line1: String,
line2: String,
city: String,
county: String,
state : String,
country_code: String,
postal_code: String
)
将 json 转换为 Scala case class 对象的语句失败:
implicit val testReads = Json.reads[PersonUser]
错误说:
[scala-play-rest-example] $ compile
[info] Compiling 4 Scala sources to C:\Personal\Scala\scala-play-rest-example-master\target\scala-2.11\classes...
[error] C:\Personal\Scala\scala-play-rest-example-master\app\controllers\user\UserController.scala:16: **No implicit Reads for List[controllers.user.Credential], controllers.user.PersonDetails available.**
[error] implicit val testReads = Json.reads[PersonUser]
有人可以帮我找出一种在 Scala 中表示复杂 json 结构并使用 Macro Inception 或其他方式转换它的方法吗?
您需要为所有案例 类 创建 Reads
,而不仅仅是顶级案例。例如:
case class Credential(handle:String, password:String,handle_type:String)
object Credential {
implicit val reads = Json.reads[Credential]
}
有了这些,Json.reads[PersonUser]
就可以工作了。
关于隐式 reads/writes/format 的另一种方法是在单独的辅助对象中定义它们。对象中的隐式必须以特定顺序定义,就像在您的情况下,隐式的顺序必须是:-
object JsonHelper {
implicit val nameReads = Json.reads[Name]
implicit val addressReads = Json.reads[Address] //position of 'nameReads' and 'addressReads' is interchangable
implicit val credentialReads = Json.reads[Credential]
implicit val personReads = Json.reads[PersonDetails] // similarly position of 'credentialReads' and 'personReads' is interchangable
implicit val personUserReads = Json.reads[PersonUser] //'personUserReads' will always be the last
}
从上面的代码可以看出,必须先定义嵌套层次底部的case classe的reads,然后是top case classes。
现在您只需要 'import JsonHelper._' 在您的服务中或任何您将 JsValue 转换为 scala 的地方 class。 :)
我有一个要求,传入的 JSON 对象很复杂,而且大多是嵌套的 例如:
"users": {
"utype": "PERSON",
"language":"en_FR",
"credentials": [
{
"handle": "xyz@abc.com",
"password": "123456",
"handle_type": "EMAIL"
}
],
"person_details": {
"primary": "true",
"names": [
{
"name_type": "OFFICIAL",
"title": "MR",
"given": "abc",
"family": "zat",
"middle": "pqs",
"suffix":"anathan"
}
],
"addresses": [
{
"ad_type": "HOME",
"line1": "Residential 2211 North 1st Street",
"line2": "Bldg 17",
"city": "test",
"county": "Shefield",
"state" : "NY",
"country_code": "xx",
"postal_code": "95131"
}
]
}
}
为了解析这个结构,我使用下面的案例 类
case class PersonUser (
user_type:String,
language_code:String,
credentials:List[Credential],
person_details:PersonDetails
)
case class Credential(handle:String, password:String,handle_type:String)
case class PersonDetails(
primary_user:Boolean,
names: List[Name],
addresses:List[Address]
)
case class Name(
name_type: String,
title: String,
given: String,
family: String,
middle: String,
suffix:String
)
case class Address(
address_type: String,
line1: String,
line2: String,
city: String,
county: String,
state : String,
country_code: String,
postal_code: String
)
将 json 转换为 Scala case class 对象的语句失败:
implicit val testReads = Json.reads[PersonUser]
错误说:
[scala-play-rest-example] $ compile
[info] Compiling 4 Scala sources to C:\Personal\Scala\scala-play-rest-example-master\target\scala-2.11\classes...
[error] C:\Personal\Scala\scala-play-rest-example-master\app\controllers\user\UserController.scala:16: **No implicit Reads for List[controllers.user.Credential], controllers.user.PersonDetails available.**
[error] implicit val testReads = Json.reads[PersonUser]
有人可以帮我找出一种在 Scala 中表示复杂 json 结构并使用 Macro Inception 或其他方式转换它的方法吗?
您需要为所有案例 类 创建 Reads
,而不仅仅是顶级案例。例如:
case class Credential(handle:String, password:String,handle_type:String)
object Credential {
implicit val reads = Json.reads[Credential]
}
有了这些,Json.reads[PersonUser]
就可以工作了。
关于隐式 reads/writes/format 的另一种方法是在单独的辅助对象中定义它们。对象中的隐式必须以特定顺序定义,就像在您的情况下,隐式的顺序必须是:-
object JsonHelper {
implicit val nameReads = Json.reads[Name]
implicit val addressReads = Json.reads[Address] //position of 'nameReads' and 'addressReads' is interchangable
implicit val credentialReads = Json.reads[Credential]
implicit val personReads = Json.reads[PersonDetails] // similarly position of 'credentialReads' and 'personReads' is interchangable
implicit val personUserReads = Json.reads[PersonUser] //'personUserReads' will always be the last
}
从上面的代码可以看出,必须先定义嵌套层次底部的case classe的reads,然后是top case classes。
现在您只需要 'import JsonHelper._' 在您的服务中或任何您将 JsValue 转换为 scala 的地方 class。 :)