简体   繁体   中英

how to parse a complicated json in Scala

I am a real newbie in Scala (Using Play framework) and trying to figure out what would be the best way to parse a complicated JSON.

This is an example I have: { "id":"test1", "tmax":270, "at":2, "bcat":[ "IAB26", "IAB25", "IAB24" ],

   "imp":[
      {
         "id":"1",
         "banner":{
            "w":320,
            "h":480,
            "battr":[
               10
            ],
            "api":[
            ]
         },
         "bidfloor":0.69
      }
   ],
   "app":{
      "id":"1234",
      "name":"Video Games",
      "bundle":"www.testapp.com",
      "cat":[
         "IAB1"
      ],
      "publisher":{
         "id":"1111"
      }
   },
   "device":{
      "dnt":0,
      "connectiontype":2,
      "carrier":"Ellijay Telephone Company",
      "dpidsha1":"e5f61ae0597d8abee94860d66f7d512aa68d0985",
      "dpidmd5":"c1827fe90bae819017dfdb30db7e84fa",
      "didmd5":"1f6cb9dc519db8e48cf9592b31cce04e",
      "didsha1":"2e6a5d7f5fd1b2b5dea56a80f2b9dc24902a0ca7",
      "ifa":"422aeb3a-6507-40b5-9e6f-42a0e14b51be",
      "osv":"4.4",
      "os":"Android",
      "ua":"Mozilla/5.0 (Linux; Android 4.4.2; DL1010Q Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36",
      "ip":"24.75.160.74",
      "devicetype":1,
      "geo":{
         "type":1,
         "country":"USA",
         "city":"Jasper"
      }
   },
   "user":{
      "id":"9c2be7c2a3dfe19070f193910e92b2e0"
   },
   "cur":[
      "USD"
   ]
   }

Thank you very much!

I would go with case classes as described in http://json4s.org/#extracting-values eg

scala> import org.json4s._
scala> import org.json4s.jackson.JsonMethods._
scala> implicit val formats = DefaultFormats // Brings in default date formats etc.
scala> case class Child(name: String, age: Int, birthdate: Option[java.util.Date])
scala> case class Address(street: String, city: String)
scala> case class Person(name: String, address: Address, children: List[Child])
scala> val json = parse("""
        { "name": "joe",
          "address": {
            "street": "Bulevard",
            "city": "Helsinki"
          },
          "children": [
            {
              "name": "Mary",
              "age": 5,
              "birthdate": "2004-09-04T18:06:22Z"
            },
            {
              "name": "Mazy",
              "age": 3
            }
          ]
        }
      """)

scala> json.extract[Person]
res0: Person = Person(joe,Address(Bulevard,Helsinki),List(Child(Mary,5,Some(Sat Sep 04 18:06:22 EEST 2004)), Child(Mazy,3,None)))

Use implicit to automatically fetch json value with the same name.

if you have a string like

    val jsonString =
   { "company": {
            "name": "google",
            "department": [
               {
                   "name": "IT",
                   "members": [
                     {
                        "firstName": "Max",
                        "lastName": "Joe",
                        "age" : 25
                     },
                     {
                        "firstName": "Jean",
                        "lastName": "Nick",
                        "age" : 55,
                        "salary": 100,000
                     }
                   ]
               },
               {
                   "name": "Marketing"
                   "members": [
                      {
                        "firstName": "Mike",
                        "lastName": "Lucas",
                        "age" : 43 
                      }
                   ] 
               },
            ]
        }
       }

Then we should do as following to parse it into scala object

val json: JsValue = Json.parse(jsonString)    // string to JsValue
case class Person(firstName: String, lastName: String, age: Int, salary: Option[Int]) // keep the lower level object above since you will use them below
implicit personR = Json.reads[Person]  
// implicit will read the json attribute if you use the same name as it is in json String. For example "name" : "google" will be read if you have Company(name: String). See the "name" and name:String .

case class Department(name: String, members: Seq[Person])
implicit departmentR = Json.reads[Department]

case class Company(name: String, department: Seq[Department])
implicit val companyR = Json.reads[Company]

val result = json.validate[Company] match {
  case s: JsSuccess[Company] => s.get  // s.get will return a Company object 
  case e: JsError => println("error")
}

Don't know if it can be used standalone, but Play Framework has great tools to work with JSON. Take a look here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM