Friday, February 26, 2016

SprayJson Scala case classes for Google Maps API response

Hi

I have played a little with Spray Json - A lightweight, clean and simple JSON implementation in Scala

Here is an example of how to easily marshalling a google get reponse for some adderss, using Spray Json and case classes that were built for the responding json.

I hope that anyone who are trying to do so, would save a little time by using the ready to use case classes (Maybe it's a good idea to create a central repository of case classes for common used jsons).

That's the 1st result for searching "melbourne australia" in google maps (originally an array of  2 results).:


 {  
   "results" : [  
    {  
      "address_components" : [  
       {  
         "long_name" : "Melbourne",  
         "short_name" : "Melbourne",  
         "types" : [ "colloquial_area", "locality", "political" ]  
       },  
       {  
         "long_name" : "Victoria",  
         "short_name" : "VIC",  
         "types" : [ "administrative_area_level_1", "political" ]  
       },  
       {  
         "long_name" : "Australia",  
         "short_name" : "AU",  
         "types" : [ "country", "political" ]  
       }  
      ],  
      "formatted_address" : "Melbourne VIC, Australia",  
      "geometry" : {  
       "bounds" : {  
         "northeast" : {  
          "lat" : -37.4598457,  
          "lng" : 145.76474  
         },  
         "southwest" : {  
          "lat" : -38.2607199,  
          "lng" : 144.3944921  
         }  
       },  
       "location" : {  
         "lat" : -37.814107,  
         "lng" : 144.96328  
       },  
       "location_type" : "APPROXIMATE",  
       "viewport" : {  
         "northeast" : {  
          "lat" : -37.4598457,  
          "lng" : 145.76474  
         },  
         "southwest" : {  
          "lat" : -38.2607199,  
          "lng" : 144.3944921  
         }  
       }  
      },  
      "partial_match" : true,  
      "place_id" : "ChIJ90260rVG1moRkM2MIXVWBAQ",  
      "types" : [ "colloquial_area", "locality", "political" ]  
    }
   ],  
   "status" : "OK"  
 }  

And that's the Code, including the case classes that are used for parsing the json:

 /**  
  * Created by gilad on 24/02/16.  
  */  
 import spray.json._  
 import DefaultJsonProtocol._  
 import scala.io.Source.fromURL  
 object FetchCoordinates extends App{  
  
  @throws(classOf[java.io.IOException])  
  @throws(classOf[java.net.SocketTimeoutException])  
  def get(url: String,  
      connectTimeout:Int =5000,  
      readTimeout:Int =5000,  
      requestMethod: String = "GET") = {  
   import java.net.{URL, HttpURLConnection}  
   val connection = (new URL(url)).openConnection.asInstanceOf[HttpURLConnection]  
   connection.setConnectTimeout(connectTimeout)  
   connection.setReadTimeout(readTimeout)  
   connection.setRequestMethod(requestMethod)  
   val inputStream = connection.getInputStream  
   val content = io.Source.fromInputStream(inputStream).mkString  
   if (inputStream != null) inputStream.close  
   content  
  }  
  try {  
   val address = "melbourneaustralia"  
   val content = get("http://maps.googleapis.com/maps/api/geocode/json?address="+address+"&sensor=true")  
   val contentJs=content.parseJson  
   val googleRes = contentJs.convertTo[GoogleMapResponse]  
   val form_address= googleRes.results(0).formatted_address  
   println(googleRes.status)  
  } catch {  
   case ioe: java.io.IOException => // handle this  
   case ste: java.net.SocketTimeoutException => // handle this  
  }  
 }  

Case classes:


 import spray.json._  
 import DefaultJsonProtocol._  
 case class JsonCoords(lat:Long,lng:Long)  
 object JsonCoords { implicit val f = jsonFormat2(JsonCoords.apply)}  
 case class JsonBounds(northeast:JsonCoords,southwest:JsonCoords)  
 object JsonBounds { implicit val f = jsonFormat2(JsonBounds.apply)}  
 case class JsonGeometry(bounds:JsonBounds,location_type:String, viewport: JsonBounds)  
 object JsonGeometry { implicit val f = jsonFormat3(JsonGeometry.apply)}  
 case class JsonAddress(long_name:String,short_name:String,types:Seq[String])  
 object JsonAddress { implicit val f = jsonFormat3(JsonAddress.apply)}  
 case class JsonGoogleResult(address_components:Seq[JsonAddress],formatted_address:String,  
               geometry:JsonGeometry,partial_match:Boolean,place_id:String,types:Seq[String]  
                )  
 object JsonGoogleResult { implicit val f = jsonFormat6(JsonGoogleResult.apply)}  
 case class GoogleMapResponse(results:Seq[JsonGoogleResult],status:String)  
 object GoogleMapResponse { implicit val f = jsonFormat2(GoogleMapResponse.apply)}  

No comments:

Post a Comment