Groovy JSON/GPath query - json

Given the following JSON, I would like to extract the postal_code (either long_name or short_name). I've used JsonSlurper to ingest it into a variable and have tried various queries using find/contains/etc. to grab the node that has "postal_code" in its "types" but haven't been able to figure it out. Any help is greatly appreciated.
{
"results" : [
{
"address_components" : [
{
"long_name" : "Jefferson Ave",
"short_name" : "Jefferson Ave",
"types" : [ "route" ]
},
{
"long_name" : "North Newport News",
"short_name" : "North Newport News",
"types" : [ "neighborhood", "political" ]
},
{
"long_name" : "Newport News",
"short_name" : "Newport News",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Virginia",
"short_name" : "VA",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
},
{
"long_name" : "23608",
"short_name" : "23608",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "Jefferson Ave & Denbigh Blvd, Newport News, VA 23608, USA",
"geometry" : {
"location" : {
"lat" : 37.13852930,
"lng" : -76.52013079999999
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 37.13987828029151,
"lng" : -76.51878181970848
},
"southwest" : {
"lat" : 37.13718031970851,
"lng" : -76.52147978029149
}
}
},
"types" : [ "intersection" ]
}
],
"status" : "OK"
}

The following should find the node with a postal_code type. If the results or address_components ever have multiple list items you would have to adjust accordingly by replacing the indexed access with some iteration, but hopefully this helps.
import groovy.json.*
def text = '''
{
"results" : [
<omitted rest to save space>
....
}
'''
def json = new JsonSlurper().parseText(text)
def theNode = json.results[0]
.address_components
.find { it.types[0] == 'postal_code' }
assert '23608' == theNode.long_name

Related

Google maps API gives different results in browser vs made from http client, components parameter behaves different in browser vs app as well

I've seen this problem mentioned in other threads but they are often using older versions of google maps and are no longer valid.
If I use the request parameters and access the following url (https://maps.googleapis.com/maps/api/geocode/json?region=ca&address=10+York+Street%2C+Sydney%2C+NS%2C+Canada&key=API_KEY) directly in my browser I get the following response:
{
"results" : [
{
"address_components" : [
{
"long_name" : "10",
"short_name" : "10",
"types" : [ "street_number" ]
},
{
"long_name" : "York Street",
"short_name" : "York St",
"types" : [ "route" ]
},
{
"long_name" : "Sydney",
"short_name" : "Sydney",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Cape Breton Regional Municipality",
"short_name" : "Cape Breton Regional Municipality",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Nova Scotia",
"short_name" : "NS",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "Canada",
"short_name" : "CA",
"types" : [ "country", "political" ]
},
{
"long_name" : "B1P 6B1",
"short_name" : "B1P 6B1",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "10 York St, Sydney, NS B1P 6B1, Canada",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 46.1427341,
"lng" : -60.19779020000001
},
"southwest" : {
"lat" : 46.1425438,
"lng" : -60.1980493
}
},
"location" : {
"lat" : 46.1426556,
"lng" : -60.19790510000001
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 46.14398793029149,
"lng" : -60.19657076970849
},
"southwest" : {
"lat" : 46.1412899697085,
"lng" : -60.1992687302915
}
}
},
"place_id" : "ChIJl_ddHCz7Z0sRQmXbPQOCT90",
"plus_code" : {
"compound_code" : "4RV2+3R Sydney, NS, Canada",
"global_code" : "87RX4RV2+3R"
},
"types" : [ "premise" ]
}
],
"status" : "OK"
}
Which is what I'm looking for. Great.
However if I make that same request in my program I get the wrong place, namely the same street address but in Ontario:
{
"results" : [
{
"address_components" : [
{
"long_name" : "10",
"short_name" : "10",
"types" : [ "street_number" ]
},
{
"long_name" : "York Street",
"short_name" : "York St",
"types" : [ "route" ]
},
{
"long_name" : "Old Toronto",
"short_name" : "Old Toronto",
"types" : [ "political", "sublocality", "sublocality_level_1" ]
},
{
"long_name" : "Toronto",
"short_name" : "Toronto",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Toronto",
"short_name" : "Toronto",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Ontario",
"short_name" : "ON",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "Canada",
"short_name" : "CA",
"types" : [ "country", "political" ]
},
{
"long_name" : "M5J 0E1",
"short_name" : "M5J 0E1",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "10 York St, Toronto, ON M5J 0E1, Canada",
"geometry" : {
"location" : {
"lat" : 43.64109759999999,
"lng" : -79.38122469999999
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 43.64244658029149,
"lng" : -79.37987571970848
},
"southwest" : {
"lat" : 43.6397486197085,
"lng" : -79.3825736802915
}
}
},
"place_id" : "ChIJBQZc3pM1K4gRIf5tNOFZWxI",
"plus_code" : {
"compound_code" : "JJR9+CG Toronto, ON, Canada",
"global_code" : "87M2JJR9+CG"
},
"types" : [ "establishment", "point_of_interest" ]
}
],
"status" : "OK"
}
If I change the address to 12 York Street in my app everything is working great and it shows me the NS address. I guess Google has it out for this one particular address. I make the request in my app with the following code:
$response = $this->client->request('GET', 'geocode/json?', [
'query' => [
'key' => Config::get('services.googleMaps')['key'],
'region' => $this->ccTLD,
'address' => urlencode($this->searchstr),
]
]);
$jsonString = $response->getBody()->getContents();
Log::info($jsonString); // Shows response quoted up above
Where region is 'ca', and address is '10+York+Street%2C+Sydney%2C+NS%2C+Canada'. The client here is a standard GuzzleHttp Client:
$this->client = new Client([
'base_uri' => 'https://maps.googleapis.com/maps/api/'
]);
I've tried using adding the bounds parameter with no difference at all, but the components parameter did ...do something for me. If I add '&components=administrative_area:NS' to the request in my browser (which starts off showing me NS) there is no change as expected.
If I then go back to my http client and add 'components' => 'administrative_area:NS', I would expect that to be the fix, right? Well no, I get ZERO RESULTS.
Out of curiosity I went back to the browser and tried to use administrative_area:ON to force it to show me the Ontario address. I instead was shown ZERO RESULTS in the browser now instead.
Does anyone know how to make my request in the client work correctly? or know why it is behaving completely differently in the first place? Is there a problem with GuzzleHttp I don't know about that could be responsible? I'm completely baffled here.

Google Maps API Doesn't Return LatLng from Extended Zip Code - USA - 9 digit Zip code

The following shows Lat and Long
https://maps.googleapis.com/maps/api/geocode/json?address=90005
But with extended Zip code, it doesn't
https://maps.googleapis.com/maps/api/geocode/json?address=900053200
{
"results" : [],
"status" : "ZERO_RESULTS"
}
Is there a separate service for extended Zip codes?
The format required for zip + 4 is 90005-3200.
Using that format gives me a result (the same result as for zip code 90005).
https://maps.googleapis.com/maps/api/geocode/json?address=90005-3200&key=MY-API-KEY
returns:
{
"results" : [
{
"address_components" : [
{
"long_name" : "90005",
"short_name" : "90005",
"types" : [ "postal_code" ]
},
{
"long_name" : "Central LA",
"short_name" : "Central LA",
"types" : [ "neighborhood", "political" ]
},
{
"long_name" : "Los Angeles",
"short_name" : "Los Angeles",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Los Angeles County",
"short_name" : "Los Angeles 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" ]
}
],
"formatted_address" : "Los Angeles, CA 90005, USA",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 34.0637149,
"lng" : -118.282294
},
"southwest" : {
"lat" : 34.05513,
"lng" : -118.3393861
}
},
"location" : {
"lat" : 34.0578814,
"lng" : -118.3096648
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 34.0637149,
"lng" : -118.282294
},
"southwest" : {
"lat" : 34.05513,
"lng" : -118.3393861
}
}
},
"partial_match" : true,
"place_id" : "ChIJ0U_geYS4woAR6-RMnUWG2Gc",
"types" : [ "postal_code" ]
}
],
"status" : "OK"
}

Parsing Json Google GeoMaps

I am trying to parse a response from google maps, this is the JSON response.
{ "results" : [ { "address_components" : [ { "long_name" : "11", "short_name" : "11", "types" : [ "street_number" ] }, { "long_name" : "Shottermill", "short_name" : "Shottermill", "types" : [ "route" ] }, { "long_name" : "Horsham", "short_name" : "Horsham", "types" : [ "postal_town" ] }, { "long_name" : "West Sussex", "short_name" : "West Sussex", "types" : [ "administrative_area_level_2", "political" ] }, { "long_name" : "England", "short_name" : "England", "types" : [ "administrative_area_level_1", "political" ] }, { "long_name" : "United Kingdom", "short_name" : "GB", "types" : [ "country", "political" ] }, { "long_name" : "RH12 5HG", "short_name" : "RH12 5HG", "types" : [ "postal_code" ] } ], "formatted_address" : "11 Shottermill, Horsham RH12 5HG, UK", "geometry" : { "location" : { "lat" : 51.084119, "lng" : -0.2948757 }, "location_type" : "ROOFTOP", "viewport" : { "northeast" : { "lat" : 51.0854679802915, "lng" : -0.2935267197084979 }, "southwest" : { "lat" : 51.0827700197085, "lng" : -0.296224680291502 } } }, "place_id" : "ChIJ0ZUiT-_rdUgRadZ4jXXzam4", "types" : [ "street_address" ] } ], "status" : "OK" }
If i want to for example echo out geometry( lat and lng) , how do i do this.
I have tried : ($content contains the above response)
$json = json_decode($content);
echo $json->results->geometry->location->lat;
echo $json->results->geometry->location->lng;
The results is in an array, you should access it using by index
$json->results[0]->geometry->location->lat;
Check the documentation to see if the results array could have a length different to 1. If it is, you will need to iterate through it.

Filtering JSON data with the same name

I'm using JSON in Google Sheets to lookup a Zip and find the county. I only want the county returned. I can get it to return every value so the ImportJSON function is working.
Here's my formula. I've tried all permutations of the reference but I just don't know how to format it.
=ImportJSON(CONCATENATE("https://maps.googleapis.com/maps/api/geocode/json?address="92660), "results/address_components/long_name[3]", "noHeaders")
Here's the JSON data from Google Maps Geocoding API. I only want the county long name. In this example it's, "Orange County".
{
"results" : [
{
"address_components" : [
{
"long_name" : "92660",
"short_name" : "92660",
"types" : [ "postal_code" ]
},
{
"long_name" : "Newport Beach",
"short_name" : "Newport Beach",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Orange County",
"short_name" : "Orange 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" ]
}
],
"formatted_address" : "Newport Beach, CA 92660, USA",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 33.671823,
"lng" : -117.841337
},
"southwest" : {
"lat" : 33.6040739,
"lng" : -117.909447
}
},
"location" : {
"lat" : 33.6301328,
"lng" : -117.8721676
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 33.671823,
"lng" : -117.841337
},
"southwest" : {
"lat" : 33.6040739,
"lng" : -117.909447
}
}
},
"place_id" : "ChIJRdSajSne3IAR8T4A2x-wgrE",
"types" : [ "postal_code" ]
}
],
"status" : "OK"
}
There are 3 things that are preventing it to properly import:
specifically in the concatenate function you have address="92660
which should be address=",92660
or you can eliminate the concat function altogether and format the url like this:
"https://maps.googleapis.com/maps/api/geocode/json?address="&"92660"
or technically point to the cell such as A1 with the 92660 value e.g. "https://maps.googleapis.com/maps/api/geocode/json?address="&A1
your missing the beginning / in front of results
In order to get the 3rd item, instead of using [3] , wrap your formula in the index function and reference the index of 3
the full thing:
=index(importjson("https://maps.googleapis.com/maps/api/geocode/json?address="&A1,"/results/address_components/long_name","noHeaders"),3)
You don't give a lot of details, but what about just parsing the json, and then doing results["address_components"][2]["long_name"]?

MySQL: filter by value in a JSON string?

I'm trying to implement a query that computes the distance between two pairs of lat/lgn. Assume that my lat/lng values are in a JSON string, would such a query be possible (I'm assuming some string functions might be needed first to extract lat/lng)? And if possible, is it a good idea to do it? Will it scale? Or am I better off having separate columns in the database specifically for lat/lng values?
Example JSON:
{
"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.4220352,
"lng" : -122.0841244
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 37.42338418029149,
"lng" : -122.0827754197085
},
"southwest" : {
"lat" : 37.4206862197085,
"lng" : -122.0854733802915
}
}
},
"place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"types" : [ "street_address" ]
}
],
"status" : "OK"
}