无法使用JSON Macro Inception将嵌套的JSON结构转换为Scala案例类对象

时间:2015-04-11 20:16:29

标签: json scala macros playframework-2.0

我有一个要求,即传入的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 Classes

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案例类对象的语句失败:

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或其他方式转换它吗?

2 个答案:

答案 0 :(得分:4)

您需要为所有案例类创建Reads,而不仅仅是顶层。例如:

case class Credential(handle:String, password:String,handle_type:String)

object Credential {

  implicit val reads = Json.reads[Credential]

}

一旦你拥有了这些,Json.reads[PersonUser]将能够工作。

答案 1 :(得分:1)

关于隐式读/写/格式的另一种方法可以是在单独的辅助对象中定义它们。必须按照特定顺序定义对象中的隐含,例如,隐式的顺序必须是: -

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的读取,然后是大写的类。

现在您只需要在服务中或在将JsValue转换为scala案例类的任何地方“导入JsonHelper._”。 :)