1

I've written something that will get the longitude and latitude from a Google Geocode Callout.

The response we get from a generic callout looks like this:

{  
   results=(   {  
      address_components=(      {  
         long_name=1600,
         short_name=1600,
         types=(street_number 
    )
      },
      {  
         long_name=Amphitheatre Parkway,
         short_name=Amphitheatre Pkwy,
         types=(route)
      },
      {  
         long_name=Mountain View,
         short_name=Mountain View,
         types=(locality,
         political)
      },
      {  
         long_name=Santa Clara County,
         short_name=Santa Clara County,
         types=(administrative_area_level_2,
         political)
      },
      {  
         long_name=California,
         short_name=CA,
         types=(administrative_area_level_1,
         political)
      },
      {  
         long_name=United States,
         short_name=US,
         types=(country,
         political)
      },
      {  
         long_name=94043,
         short_name=94043,
         types=(postal_code)
      }      ),
      formatted_address=1600 Amphitheatre Pkwy,
      Mountain View,
      CA 94043,
      USA,
      geometry=      {  
         location=         {  
            lat=37.4223582,
            lng=-122.0844464
         },
         location_type=ROOFTOP,
         viewport=         {  
            northeast=            {  
               lat=37.4237071802915,
               lng=-122.0830974197085
            },
            southwest=            {  
               lat=37.4210092197085,
               lng=-122.0857953802915
            }
         }
      },
      place_id=ChIJ2eUgeAK6j4ARbn5u_wAGqWA,
      types=(street_address)
   }   ),
   status=OK
}

Specifically I'm interested in the following part:

  geometry=      {  
     location=         {  
        lat=37.4223582,
        lng=-122.0844464
     },

I've written a small HTTP class that parses through the response and puts the Longitude and Latitude into the Double lng, lat; variables that can then be processed into a Geolocation field.

Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=[MY_API_KEY]');
request.setMethod('GET');

HttpResponse response = http.send(request);

Double lat, lng;

if (response.getStatusCode() == 200) {
    JSONParser parser = JSON.createParser(response.getBody());

    while (parser.nextToken() != null) {
        if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'geometry') {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'location') {
                    while (parser.nextToken() != JSONToken.END_OBJECT) {



                        if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'lat') {
                            parser.nextToken();
                            lat = Double.valueOf(parser.getText());
                        }

                        if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'lng') {
                            parser.nextToken();
                            lng = Double.valueOf(parser.getText());
                        }

                    }
                }
            }
        }
    }
}

System.debug('@@@@@ Lat: ' + lat);
System.debug('@@@@@ Lng: ' + lng);

Whilst this works, I'm not convinced I'm parsing it in the best way possible and that with so many while iterations and if statements that it couldn't be more efficient.

Is there a better way to parse through a JSON response, such as what Google provides from a Geocoder response?

4
  • 2
    Just use the heroku JSON2apex app and deserialize the response into an object. json2apex.herokuapp.com Commented Feb 3, 2017 at 17:05
  • 2
    The response you have posted is not valid JSON.
    – Keith C
    Commented Feb 3, 2017 at 17:05
  • @KeithC I did think that, but wasn't 100% sure has I ripped the response from the debug logs. Maybe I've done something wrong. It is interesting that the code above works, given that though. Unless debugging it strips things out?
    – Dan Jones
    Commented Feb 3, 2017 at 18:25
  • Not sure why you are seeing that output. JSON is this simple, just pretty much { } [ ] : plus numbers and quoted strings.
    – Keith C
    Commented Feb 3, 2017 at 19:27

1 Answer 1

5

Not a parser! Just deserialize:

public class Response { final Geometry geometry; }
public class Geometry { final Location location; }
public class Location { final Decimal latitude, longitude; }

Granted, your JSON payload is not valid as currently specified. The above would work though if your structure boils down to:

{
    "geometry": {
        "location": {
            "latitude": 0.0,
            "longitude": 0.0
        }
    },
    "other_properties": { /*values*/ }
}

If you want to copy the payload format listed here, the class would be slightly different.

JSON

{
   "results" : [
      {
         "address_components" : [...],
         "formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
         "geometry" : {
            "location" : {
               "lat" : 37.4224764,
               "lng" : -122.0842499
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 37.4238253802915,
                  "lng" : -122.0829009197085
               },
               "southwest" : {
                  "lat" : 37.4211274197085,
                  "lng" : -122.0855988802915
               }
            }
         },
         "place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
         "types" : [ "street_address" ]
      }
   ],
   "status" : "OK"
}

Apex

public class Response { final List<Result> results; }
public class Result { final Geometry geometry; }
public class Geometry { final Location location; }
public class Location { final Decimal latitude, longitude; }
4
  • Obligatory link: json2apex.herokuapp.com.
    – sfdcfox
    Commented Feb 3, 2017 at 17:21
  • Except that's going to give you a bunch of irrelevant structure you don't care about. It's not rocket surgery converting JSON structure to an Apex Class representation. When you just want to cherry pick a small portion of the structure, I personally would avoid using that tool.
    – Adrian Larson
    Commented Feb 3, 2017 at 17:27
  • Can you make your answer more complete? Based on developers.google.com/maps/documentation/geocoding/intro there is an array to deal with too.
    – Keith C
    Commented Feb 3, 2017 at 17:51
  • I'll give that a go. Thanks Adrian! And thanks @sfdcfox. I should've mentioned I was aware of that, but I'm intentionally trying to reinvent the wheel a bit. Purely so I understand "GET" HTTP callouts a bit better (pun not initially intended, but now is).
    – Dan Jones
    Commented Feb 3, 2017 at 18:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .