Google places API hierarchy - neighbourhood/suburb -> city -> region -> country - json

Problem -
people posting in various places based on their interest while other people are searching for posts in greater areas.
e.g. - user A posts under Bondi Beach, a suburb of Sydney.
user B searches for posts under Sydney.
Desired outcome - user B gets to see user A's post since Bondi is located inside Sydney.
Solution:
Find in Google places API where it tells you that suburb X is of city Y and so forth.
In my example - I would like to get information about Bondi that tells me to which city it belongs.
Here is my simple query for Bondi Beach (I use auto complete because it's an autocomplete dropdown):
https://maps.googleapis.com/maps/api/place/autocomplete/json?sensor=true&input=bondi%20beach&key=myKey
{
"predictions" : [
{
"description" : "Bondi Beach, New South Wales, Australia",
"id" : "ffa6ad484d2fec594378fb2a24e8328a2bc4459f",
"matched_substrings" : [
{
"length" : 11,
"offset" : 0
}
],
"place_id" : "ChIJWTi8xgGyEmsRgK0yFmh9AQU",
"reference" : "CkQ_AAAAMnfwZeK5SV6uPBnPr34JVdHudAGxMtna--JWHtwe7t81gLBGgsB6mRgmj375m7KReRhpMq1Y6AYxCrC2MnYn8hIQQfASvoG5-7LwRcVR7ELjNxoURh-iBs6M2dmrU8wLKIPcFFgymn4",
"terms" : [
{
"offset" : 0,
"value" : "Bondi Beach"
},
{
"offset" : 13,
"value" : "New South Wales"
},
{
"offset" : 30,
"value" : "Australia"
}
],
"types" : [ "locality", "political", "geocode" ]
},
{
"description" : "Bondi Beachouse YHA, Fletcher Street, Bondi Beach, New South Wales, Australia",
"id" : "fdab345a9db5c6cfcddd7cd561a8b83acc538d73",
"matched_substrings" : [
{
"length" : 11,
"offset" : 0
}
],
"place_id" : "ChIJzwpdVYStEmsRd6F0Wa1NQ2I",
"reference" : "CmRbAAAA_AFGY8xaYlQebohzYWKrvNoMiJAktObvU4Vb03ORpmf7-ZTlv3BkU3dJPdAIBMtgol8ngdxC1NhVZA7AsAnkRfe4WPT7GJlqkIa_S0Hsb87Dlt-OT1Dt5uQNg_ei4cRPEhCvI7pwL5qD1US6yrOxvVpXGhRQxfEObV1zUxys2a2EZTkbKUdMbg",
"terms" : [
{
"offset" : 0,
"value" : "Bondi Beachouse YHA"
},
{
"offset" : 21,
"value" : "Fletcher Street"
},
{
"offset" : 38,
"value" : "Bondi Beach"
},
{
"offset" : 51,
"value" : "New South Wales"
},
{
"offset" : 68,
"value" : "Australia"
}
],
"types" : [ "establishment" ]
},
{
"description" : "Bondi Beach Car Park, Campbell Parade, Bondi Beach, New South Wales, Australia",
"id" : "ba6c34f150f7f3ac035d731662f2a08a22a3b5dd",
"matched_substrings" : [
{
"length" : 11,
"offset" : 0
}
],
"place_id" : "ChIJXch67J6tEmsRFXD11Ce64WA",
"reference" : "CmRcAAAA_H6cxlTUVW2JHFb5EO0MQAL-d1M-_6_DXOQAvw6xJOFSri4HaIvodY6lcZH3F8rrAlyaXqOM4lcgbegqvVEPScyRE20iiJSXC6jHPxH5EwplZGPWx7rxy34l1uweXgmhEhBirrakiRpK-Zd_naBW7Hd8GhTiujZAiOEDsWj9tuP3bumLR6SamQ",
"terms" : [
{
"offset" : 0,
"value" : "Bondi Beach Car Park"
},
{
"offset" : 22,
"value" : "Campbell Parade"
},
{
"offset" : 39,
"value" : "Bondi Beach"
},
{
"offset" : 52,
"value" : "New South Wales"
},
{
"offset" : 69,
"value" : "Australia"
}
],
"types" : [ "establishment" ]
},
{
"description" : "Bondi Beach Public School, Campbell Parade, Bondi Beach, New South Wales, Australia",
"id" : "e808bb9453705761b5b1672065a5aaa5b1b5b52a",
"matched_substrings" : [
{
"length" : 11,
"offset" : 0
}
],
"place_id" : "ChIJaXfeKJ6tEmsRM_pgTjpurLs",
"reference" : "CnRiAAAAN-CRd33lyhCZBryEwtPxVdxweAC-WcxikMSlmiP83st3Eu0qt5tOdx_Kxvfb6aTH_F3szZETbrRYSXb8-Ql-NSdXFhIeZjIf3au9qrwIII7y9-ZhFRImHCeYRJ1xslrS2dal0_lulOh_dY39jgofrRIQoVco7kZBb4DgSaACK9h4ARoUf98GpsdtuHPVY615rIszSUVqRpM",
"terms" : [
{
"offset" : 0,
"value" : "Bondi Beach Public School"
},
{
"offset" : 27,
"value" : "Campbell Parade"
},
{
"offset" : 44,
"value" : "Bondi Beach"
},
{
"offset" : 57,
"value" : "New South Wales"
},
{
"offset" : 74,
"value" : "Australia"
}
],
"types" : [ "establishment" ]
},
{
"description" : "Bondi Beach View, Campbell Parade, Sydney, New South Wales, Australia",
"id" : "16758032a0384967c04985914cd861dc2c488fe8",
"matched_substrings" : [
{
"length" : 11,
"offset" : 0
}
],
"place_id" : "ChIJr6fcCputEmsRtFcOcREuc48",
"reference" : "CmRUAAAAK3dQSHexE9SerblRCR84jdJ8ScqqDwteRMH2H1f_uCRVQNVsFmgELlMlWWCG2mMbbNOL0yQRv2K0Bx2aqKIe3Bt236LvDl5sxjDaRvdd7QTdBATMJsTHec-xXc3z9c02EhC-JDoD5ln1Q-qdeb-urugLGhSur_7TThy4ekl9yoXRFzZwZmn26w",
"terms" : [
{
"offset" : 0,
"value" : "Bondi Beach View"
},
{
"offset" : 18,
"value" : "Campbell Parade"
},
{
"offset" : 35,
"value" : "Sydney"
},
{
"offset" : 43,
"value" : "New South Wales"
},
{
"offset" : 60,
"value" : "Australia"
}
],
"types" : [ "establishment" ]
}
],
"status" : "OK"
}
As you can see, the only result that tells me that Bondi is part of Sydney is the "Bondi Beach View", which doesn't make sense nor does it help solve my problem.
I experience this issue with many other places all over the world.
How can I get accurate info of places hierarchy ?

I had similar problem. I did some research and didn't find accurate solution. Currently I'm using the following workaround which is good enough for my case.
First, get coordinates of a place (place_id you can find in autocomplete results):
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJWTi8xgGyEmsRgK0yFmh9AQU&key=yourKey
After that execute reverse geocoding requests with these coordinates and desired result_types: country, administrative_area_level_1, administrative_area_level_2, locality.
For example:
https://maps.googleapis.com/maps/api/geocode/json?latlng=-33.8914755,151.2766845&result_type=locality&key=yourKey
This is not 100% accurate approach. It gives more than one results for some locations (as you can see, Bondi Beach is one of them), but you can try to choose one by some other attributes (in this case, the result with colloquial_area type is correct one).
I hope, my answer will help you at least a little bit.

You can just
console.log(places.address_components)
then use check the console on the browser.
It will show the hierarchy and the keys you need to access the information you want. Suburb/Neighbourhood should show up as
'sublocality_level_1'

Related

Google Maps Places Autocomplete - Not Returning Street Numbers?

I'm looking to build a pretty basic address search functionality inside of my iOS app. I'm using Google Places Autocomplete to query for results based on users input, like below:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=shoppers#&radius=160934&location=50.445210,-104.618896&components=country:ca&key=xxxxxxxxxxxxx
The results I'm getting back are far too vague to be of practical use. Below is one example, where all I get is the name of the business and the street that it is on. Problem being, there are three different locations for this business on the same street, so how would the user be able to figure out which one they're selecting without being provided a street number?
{
"description" : "Shoppers Drug Mart, Albert Street, Regina, SK, Canada",
"id" : "94065830c922a4239ece26102fb3439fa2f2e155",
"matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"place_id" : "ChIJ4XzAGbCgHlMRGSFBsEbyfCE",
"reference" : "ChIJ4XzAGbCgHlMRGSFBsEbyfCE",
"structured_formatting" : {
"main_text" : "Shoppers Drug Mart",
"main_text_matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"secondary_text" : "Albert Street, Regina, SK, Canada"
},
"terms" : [
{
"offset" : 0,
"value" : "Shoppers Drug Mart"
},
{
"offset" : 20,
"value" : "Albert Street"
},
{
"offset" : 35,
"value" : "Regina"
},
{
"offset" : 43,
"value" : "SK"
},
{
"offset" : 47,
"value" : "Canada"
}
],
"types" : [ "pharmacy", "health", "point_of_interest", "store", "establishment" ]
},
Places Autocomplete is not designed to return detailed address information. It is designed to return predictions based on your input. You then have to use the Place ID that gets returned and make a Place Details request using it to get a response that includes address information, etc.
Using the first result from your autocomplete request, I can form a Place Details request like:
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJ4XzAGbCgHlMRGSFBsEbyfCE&key=YOUR_API_KEY
That will give the information you desire.
https://developers.google.com/places/web-service/autocomplete#place_autocomplete_results
https://developers.google.com/places/web-service/place-id#example-using-the-places-api

How to Parse JSON object in SWIFT properly

I have tried to parse this JSON object but it's not working.. I'm not getting an error message either.
What I'm trying to do is fetch recipe details from an API to an array but I'm unable to make it work. I can see from the console that the API call has been successful and able to print the json file.
See below the json file, object class & the parse code.
Json file
{
"recipes" : [
{
"veryHealthy" : false,
"preparationMinutes" : 20,
"vegan" : false,
"aggregateLikes" : 8,
"veryPopular" : false,
"imageType" : "jpg",
"diets" : [
"lacto ovo vegetarian"
],
"creditsText" : "BBC Good Food",
"extendedIngredients" : [
{
"originalString" : "200g unsalted butter, softened",
"name" : "unsalted butter",
"measures" : {
"metric" : {
"amount" : 200,
"unitLong" : "grams",
"unitShort" : "g"
},
"us" : {
"unitLong" : "ounces",
"amount" : 7.0549999999999997,
"unitShort" : "oz"
}
},
"consitency" : "solid",
"aisle" : "Milk, Eggs, Other Dairy",
"meta" : [
"unsalted",
"softened"
],
"image" : "butter-sliced.jpg",
"metaInformation" : [
"unsalted",
"softened"
],
"original" : "200g unsalted butter, softened",
"amount" : 200,
"originalName" : "unsalted butter, softened",
"unit" : "g",
"id" : 1145
},
{
"originalString" : "125g soft brown sugar",
"name" : "brown sugar",
"measures" : {
"us" : {
"unitLong" : "ounces",
"unitShort" : "oz",
"amount" : 4.4089999999999998
},
"metric" : {
"unitLong" : "grams",
"unitShort" : "g",
"amount" : 125
}
},
"consitency" : "solid",
"aisle" : "Baking",
"meta" : [
"soft"
],
"image" : "dark-brown-sugar.png",
"metaInformation" : [
"soft"
],
"original" : "125g soft brown sugar",
"amount" : 125,
"originalName" : "soft brown sugar",
"unit" : "g",
"id" : 19334
},
{
"originalString" : "1 tsp ground cinnamon",
"name" : "ground cinnamon",
"measures" : {
"us" : {
"unitLong" : "teaspoon",
"unitShort" : "tsp",
"amount" : 1
},
"metric" : {
"unitLong" : "teaspoon",
"unitShort" : "tsp",
"amount" : 1
}
},
"consitency" : "solid",
"aisle" : "Spices and Seasonings",
"meta" : [
],
"image" : "cinnamon.jpg",
"metaInformation" : [
],
"original" : "1 tsp ground cinnamon",
"amount" : 1,
"originalName" : "ground cinnamon",
"unit" : "tsp",
"id" : 1012010
},
{
"originalString" : "1½ tsp vanilla bean paste",
"name" : "vanilla bean paste",
"measures" : {
"us" : {
"unitLong" : "teaspoons",
"unitShort" : "tsps",
"amount" : 1.5
},
"metric" : {
"unitLong" : "teaspoons",
"unitShort" : "tsps",
"amount" : 1.5
}
},
"consitency" : "solid",
"aisle" : "Gourmet",
"meta" : [
],
"image" : "molasses.jpg",
"metaInformation" : [
],
"original" : "1½ tsp vanilla bean paste",
"amount" : 1.5,
"originalName" : "vanilla bean paste",
"unit" : "tsp",
"id" : 93813
},
{
"originalString" : "1 pineapple, peeled, cut into quarters, core removed, then cut into 2cm slices",
"name" : "pineapple",
"measures" : {
"us" : {
"unitLong" : "",
"unitShort" : "",
"amount" : 1
},
"metric" : {
"unitShort" : "",
"unitLong" : "",
"amount" : 1
}
},
"consitency" : "solid",
"aisle" : "Produce",
"meta" : [
"peeled",
"cut into quarters, core removed, then cut into 2cm slices"
],
"image" : "pineapple.jpg",
"metaInformation" : [
"peeled",
"cut into quarters, core removed, then cut into 2cm slices"
],
"original" : "1 pineapple, peeled, cut into quarters, core removed, then cut into 2cm slices",
"amount" : 1,
"originalName" : "pineapple, peeled, cut into quarters, core removed, then cut into 2cm slices",
"unit" : "",
"id" : 9266
},
{
"originalString" : "140g golden caster sugar",
"name" : "golden brown sugar",
"measures" : {
"us" : {
"unitShort" : "oz",
"unitLong" : "ounces",
"amount" : 4.9379999999999997
},
"metric" : {
"unitLong" : "grams",
"unitShort" : "g",
"amount" : 140
}
},
"consitency" : "solid",
"aisle" : "Baking",
"meta" : [
],
"image" : "dark-brown-sugar.png",
"metaInformation" : [
],
"original" : "140g golden caster sugar",
"amount" : 140,
"originalName" : "golden caster sugar",
"unit" : "g",
"id" : 19334
},
{
"originalString" : "2 large eggs, plus 1 egg white, beaten",
"name" : "eggs",
"measures" : {
"us" : {
"unitLong" : "larges",
"unitShort" : "large",
"amount" : 2
},
"metric" : {
"unitShort" : "large",
"amount" : 2,
"unitLong" : "larges"
}
},
"consitency" : "solid",
"aisle" : "Milk, Eggs, Other Dairy",
"meta" : [
"beaten"
],
"image" : "egg.png",
"metaInformation" : [
"beaten"
],
"original" : "2 large eggs, plus 1 egg white, beaten",
"amount" : 2,
"originalName" : "eggs, plus 1 egg white, beaten",
"unit" : "large",
"id" : 1123
},
{
"originalString" : "1½ tsp baking powder",
"name" : "baking powder",
"measures" : {
"us" : {
"unitShort" : "tsps",
"amount" : 1.5,
"unitLong" : "teaspoons"
},
"metric" : {
"unitLong" : "teaspoons",
"unitShort" : "tsps",
"amount" : 1.5
}
},
"consitency" : "solid",
"aisle" : "Baking",
"meta" : [
],
"image" : "white-powder.jpg",
"metaInformation" : [
],
"original" : "1½ tsp baking powder",
"amount" : 1.5,
"originalName" : "baking powder",
"unit" : "tsp",
"id" : 18371
},
{
"originalString" : "200g plain flour",
"name" : "plain flour",
"measures" : {
"us" : {
"unitLong" : "ounces",
"unitShort" : "oz",
"amount" : 7.0549999999999997
},
"metric" : {
"unitLong" : "grams",
"unitShort" : "g",
"amount" : 200
}
},
"consitency" : "solid",
"aisle" : "Baking",
"meta" : [
"plain"
],
"image" : "flour.png",
"metaInformation" : [
"plain"
],
"original" : "200g plain flour",
"amount" : 200,
"originalName" : "plain flour",
"unit" : "g",
"id" : 20081
},
{
"originalString" : "75ml whole milk",
"name" : "whole milk",
"measures" : {
"us" : {
"unitLong" : "fl. ozs",
"unitShort" : "fl. oz",
"amount" : 2.536
},
"metric" : {
"unitLong" : "milliliters",
"unitShort" : "ml",
"amount" : 75
}
},
"consitency" : "liquid",
"aisle" : "Milk, Eggs, Other Dairy",
"meta" : [
"whole"
],
"image" : "milk.png",
"metaInformation" : [
"whole"
],
"original" : "75ml whole milk",
"amount" : 75,
"originalName" : "whole milk",
"unit" : "ml",
"id" : 1077
}
],
"cuisines" : [
],
"cheap" : false,
"ketogenic" : false,
"sourceUrl" : "https:\/\/www.bbcgoodfood.com\/recipes\/cinnamon-pineapple-upside-down-cake",
"sustainable" : false,
"healthScore" : 5,
"weightWatcherSmartPoints" : 20,
"sourceName" : "BBC Good Food",
"whole30" : false,
"instructions" : "Heat oven to 180C\/160C fan\/gas 4. Put 4 tbsp of the butter into a 22cm springform cake tin and place in the oven to melt. Remove and stir in the brown sugar, cinnamon and tsp of the vanilla paste. Arrange the pineapple in the buttery sugar mixture, tossing a little to coat. Try to fill all the gaps, so you cant see much of the base.\nIn a mixing bowl, beat the caster sugar and remaining butter using an electric hand whisk for 2-3 mins until light and fluffy. Add the eggs and egg white, one at a time, and the remaining vanilla. Add the baking powder and a pinch of salt, then the flour and milk, beating until they are both incorporated. Beat for 1 min more until smooth.\nSpoon the batter into the pan over the pineapple. Bake for 1 hr, covering with foil if it starts to brown. Leave to rest for 5 mins, then turn out onto a platter and serve warm as a pudding, with crme frache, if you like. Alternatively, leave to cool completely in the tin and serve as a cake.",
"analyzedInstructions" : [
{
"steps" : [
{
"ingredients" : [
],
"number" : 1,
"step" : "Heat oven to 180C\/160C fan\/gas",
"equipment" : [
{
"name" : "oven",
"id" : 404784,
"image" : "oven.jpg",
"temperature" : {
"unit" : "Celsius",
"number" : 180
}
}
]
},
{
"ingredients" : [
],
"number" : 2,
"step" : "Put 4 tbsp of the butter into a 22cm springform cake tin and place in the oven to melt.",
"equipment" : [
{
"id" : 404747,
"image" : "cake-pan.png",
"name" : "cake form"
},
{
"id" : 404784,
"image" : "oven.jpg",
"name" : "oven"
}
]
},
{
"ingredients" : [
{
"id" : 93813,
"image" : "molasses.jpg",
"name" : "vanilla paste"
},
{
"id" : 19334,
"image" : "dark-brown-sugar.png",
"name" : "brown sugar"
},
{
"id" : 9266,
"image" : "pineapple.jpg",
"name" : "pineapple"
},
{
"id" : 2010,
"image" : "cinnamon.jpg",
"name" : "cinnamon"
}
],
"number" : 3,
"step" : "Remove and stir in the brown sugar, cinnamon and tsp of the vanilla paste. Arrange the pineapple in the buttery sugar mixture, tossing a little to coat. Try to fill all the gaps, so you cant see much of the base.",
"equipment" : [
]
},
{
"length" : {
"unit" : "minutes",
"number" : 3
},
"ingredients" : [
],
"number" : 4,
"step" : "In a mixing bowl, beat the caster sugar and remaining butter using an electric hand whisk for 2-3 mins until light and fluffy.",
"equipment" : [
{
"id" : 405907,
"image" : "mixing-bowl.jpg",
"name" : "mixing bowl"
},
{
"id" : 404661,
"image" : "whisk.png",
"name" : "whisk"
}
]
},
{
"ingredients" : [
{
"id" : 1123,
"image" : "egg.png",
"name" : "egg"
}
],
"number" : 5,
"step" : "Add the eggs and egg white, one at a time, and the remaining vanilla.",
"equipment" : [
]
},
{
"length" : {
"unit" : "minutes",
"number" : 1
},
"ingredients" : [
{
"id" : 18371,
"image" : "white-powder.jpg",
"name" : "baking powder"
},
{
"id" : 20081,
"image" : "flour.png",
"name" : "all purpose flour"
},
{
"id" : 1077,
"image" : "milk.png",
"name" : "milk"
}
],
"number" : 6,
"step" : "Add the baking powder and a pinch of salt, then the flour and milk, beating until they are both incorporated. Beat for 1 min more until smooth.",
"equipment" : [
]
},
{
"ingredients" : [
{
"id" : 9266,
"image" : "pineapple.jpg",
"name" : "pineapple"
}
],
"number" : 7,
"step" : "Spoon the batter into the pan over the pineapple.",
"equipment" : [
{
"id" : 404645,
"image" : "pan.png",
"name" : "frying pan"
}
]
},
{
"length" : {
"unit" : "minutes",
"number" : 5
},
"ingredients" : [
],
"number" : 8,
"step" : "Bake for 1 hr, covering with foil if it starts to brown. Leave to rest for 5 mins, then turn out onto a platter and serve warm as a pudding, with crme frache, if you like. Alternatively, leave to cool completely in the tin and serve as a cake.",
"equipment" : [
{
"id" : 404765,
"image" : "aluminum-foil.png",
"name" : "aluminum foil"
}
]
}
],
"name" : ""
}
],
"spoonacularSourceUrl" : "https:\/\/spoonacular.com\/cinnamon-pineapple-upside-down-cake-212615",
"vegetarian" : true,
"gaps" : "no",
"servings" : 8,
"cookingMinutes" : 65,
"title" : "Cinnamon pineapple upside-down cake",
"id" : 212615,
"image" : "https:\/\/spoonacular.com\/recipeImages\/212615-556x370.jpg",
"glutenFree" : false,
"dishTypes" : [
"dessert"
],
"lowFodmap" : false,
"winePairing" : {
"pairingText" : "Cream Sherry, Moscato d'Asti, and Port are my top picks for Cake. A common wine pairing rule is to make sure your wine is sweeter than your food. Delicate desserts go well with Moscato d'Asti, nutty desserts with cream sherry, and caramel or chocolate desserts pair well with port. The NV Johnson Estate Cream Sherry with a 5 out of 5 star rating seems like a good match. It costs about 19 dollars per bottle.",
"pairedWines" : [
"cream sherry",
"moscato dasti",
"port"
],
"productMatches" : [
{
"link" : "https:\/\/www.amazon.com\/Johnson-Estate-Cream-Sherry-750\/dp\/B00D3GQSRW?tag=spoonacular-20",
"score" : 0.85714285714285721,
"id" : 430626,
"price" : "$19.49",
"title" : "NV Johnson Estate Cream Sherry",
"imageUrl" : "https:\/\/spoonacular.com\/productImages\/430626-312x231.jpg",
"averageRating" : 1,
"description" : "Very aromatic with notes of hazelnut, vanilla, and a touch of oak followed by sweet raisins and a touch of yeast. Clean lasting finish. Good now but will reward those allow it to age\"\". A favorite pre-prandial beverage. Consider it with nuts before dinner as an aperitif, or after dinner with dessert, especially chocolates and fruit-based desserts. Also wonderful on cold afternoons, served with biscotti to dip in \"\"Italian-style\"\". \"",
"ratingCount" : 2
}
]
},
"dairyFree" : false,
"occasions" : [
],
"spoonacularScore" : 37,
"pricePerServing" : 91.790000000000006,
"readyInMinutes" : 85
}
]
}
Recipe Class
struct Recipe {
let id: Int
let name: String
// Recipes will only ever be instantiated in response to the server
init(json: JSON) {
self.id = json["id"].intValue
self.name = json["title"].stringValue
}
}
Parse code that's not working. It will return empty array.
let recipes: [Recipe] = json.arrayValue.map({ Recipe(json: $0) })
Please read the JSON carefully.
The recipes array is in the (root) dictionary for key recipes
let recipes = json["recipes"].arrayValue.map{ Recipe(json: $0) }
It's highly recommended to drop SwiftyJSON in favor of the built-in Codable protocol.
I use ObjectMapper library + JSONExport for classes codeGen.
The best way is to use Codable protocol power.
I write playground example below.
import UIKit
// Models
struct Recipe: Codable {
let id: Int
let name: String?
}
struct Response: Codable {
let recipes: [Recipe]
}
// Test JSON
let jsonString = """
{
"recipes": [
{
"id": 141892,
"name": "Codable Recipe"
},
{
"id": 908,
"name": "JSON Recipe"
}
]
}
"""
// Codable Test Drive
let data = jsonString.data(using: .utf8)!
do {
let res = try JSONDecoder().decode(Response.self, from: data)
print("recipes count: \(res.recipes.count)")
} catch {
print("decode error: \(error)")
}
console output:
recipes count: 2

Google Places API - how does google determine latitude/longitude for cities/counties?

I've tried Googling and checking the documentation for the Google Places JavaScript API but haven't been able to find an answer to this question.
When I perform a search for a specific city, like San Francisco, CA, I get a response that looks like this:
/**/_xdc_._a1fter && _xdc_._a1fter( {
"html_attributions" : [],
"result" : {
"address_components" : [
{
"long_name" : "San Francisco",
"short_name" : "SF",
"types" : [ "locality", "political" ]
},
{
"long_name" : "San Francisco County",
"short_name" : "San Francisco 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" ]
}
],
"adr_address" : "\u003cspan class=\"locality\"\u003eSan Francisco\u003c/span\u003e, \u003cspan class=\"region\"\u003eCA\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eUSA\u003c/span\u003e",
"formatted_address" : "San Francisco, CA, USA",
"geometry" : {
"location" : {
"lat" : 37.7749295,
"lng" : -122.4194155
},
"viewport" : {
"northeast" : {
"lat" : 37.812,
"lng" : -122.3482
},
"southwest" : {
"lat" : 37.70339999999999,
"lng" : -122.527
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"id" : "1b9ea3c094d3ac23c9a3afa8cd4d8a41f05de50a",
"name" : "San Francisco",
"photos" : [
{
"height" : 2448,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/103231451031314314785/photos\"\u003eTrigby Perea\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh4.googleusercontent.com/-aP4oMIc1OZ0/V2g8WKNFqpI/AAAAAAAANbU/w0Ii2GYhpyofvMqPjzEH0RcL-KkdMblEQCLIB/k/"
},
"width" : 3264
},
{
"height" : 3651,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/111642936581150005827/photos\"\u003eCraig Foster\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh5.googleusercontent.com/-Fp-Ds7Nltp0/Vke8Hc4KbZI/AAAAAAAB3lg/Zyh3nNGV_ZMhm5zFXBxQk4fToCLikK2bQ/k/"
},
"width" : 5477
},
{
"height" : 1441,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/105870396459094511944/photos\"\u003eAbbey Taylor\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh5.googleusercontent.com/-zohVGEyuXoc/VlHp_eA5DnI/AAAAAAAARKc/pyOWLnMEJnActbiE-NGo8aRxmAnLmyTgA/k/"
},
"width" : 1920
},
{
"height" : 1520,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114911123719406241256/photos\"\u003eChristine Tallon\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh6.googleusercontent.com/-4ImN1qnn6mg/V87uASQ2tOI/AAAAAAAAAH8/z_2yiFXWTdQsxG-RTTqC0_TKQROHDUkIACLIB/k/"
},
"width" : 2688
},
{
"height" : 1836,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/111652642356832495715/photos\"\u003eLau Dora\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh5.googleusercontent.com/-ylvq826HIy0/V5EgFJrFBjI/AAAAAAAAlj4/EGL_L-RflOgu6rTFVvFvUl8Wkxw3nnzJgCLIB/k/"
},
"width" : 3264
},
{
"height" : 1944,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/112904178425011771283/photos\"\u003eGlenn Meyer\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh3.googleusercontent.com/-daHOav_w_QY/V2WuYuir_1I/AAAAAAAAPso/RhsZzyz05ygoeu4kjL_4bbNEepSNn_auwCLIB/k/"
},
"width" : 3456
},
{
"height" : 2592,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/110340141477234279592/photos\"\u003eZaw Khun Naw Hpunggan\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh4.googleusercontent.com/-EjAUXW008Xo/Vmy-JD612FI/AAAAAAAAMMc/km2jOrx8-dwPYFHaTqfCw2PVMu5bQxZFA/k/"
},
"width" : 4608
},
{
"height" : 2988,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/112146856900507552674/photos\"\u003eJustin Wah Kan\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh6.googleusercontent.com/-Hk2UJFlS4HE/V2Q8KN1Q09I/AAAAAAABAMg/IFdiQdW1EfkQmIOkx_vZE1ZIQu-Oc80bQCLIB/k/"
},
"width" : 5312
},
{
"height" : 3024,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/101062424435478354204/photos\"\u003eNitesh Misra\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh6.googleusercontent.com/-KaFyc8uLu3E/V52S4rwKZ0I/AAAAAAAABNw/OoqMzR3BhWIEbP57UEYlxlhrc_JrjGZ0QCLIB/k/"
},
"width" : 4030
},
{
"height" : 3265,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/101841506952017923314/photos\"\u003eAlejandro Villa Renteria\u003c/a\u003e"
],
"raw_reference" : {
"fife_url" : "https://lh3.googleusercontent.com/-d9HUyuzGUrI/VyDZ3QJAk1I/AAAAAAACAbk/PkZyTBaBQnI233l3sDWivzPKzFmhfBU9QCLIB/k/"
},
"width" : 4898
}
],
"place_id" : "ChIJIQBpAG2ahYAR_6128GcTUEo",
"reference" : "CoQBcwAAAPXngWwN52gpBv2Gpbi1kgRDZYEO6VclmIOEH8LyQKzEf8onqG72eVhCZSEoFLHpPmO2obfQRHO34oNkSprGBSZ4Mt0PvfUcABiPGKzmO2iALQPYh5pLv_3C6yst3Y-WZFq08ZHCBk5dOUo1o3HEyDjXwxE3gPIH9IXpfYvXCn5dEhCuC8FoVZo8pKqcMpm494tcGhTh80nRCEJD3U2Aozn3Tm83E8-_Jw",
"scope" : "GOOGLE",
"types" : [ "locality", "political" ],
"url" : "https://maps.google.com/?q=San+Francisco,+CA,+USA&ftid=0x80859a6d00690021:0x4a501367f076adff",
"utc_offset" : -420,
"vicinity" : "San Francisco"
},
"status" : "OK"
}
)
The specific part of this I'm curious about is this section:
"geometry" : {
"location" : {
"lat" : 37.7749295,
"lng" : -122.4194155
},
How does Google determine these latitude and longitude values for a Place like a City or County that's actually an area?
It doesn't appear to use the geographic center of the city or any other consistent method that I can discern, and I couldn't find this mentioned anywhere in the docs.
Let me answer with a question: why do you care?
Years ago, I remember Google Maps would drop a pin in front of the city hall when searching for a city. This was fairly consistent across several countries, at last the ones I'm somewhat familiar with (Spain, Ireland, UK, USA, ...) and I always wondered, why would I want any pin point anyway?
Looking at it now, Google Maps no longer drops a pin anywhere when you search for a city, instead it highlights the relevant area. I take this as a strong signal that the point location for a big place is probably not very useful. This may be also one of the reasons why this feature request is by far the most popular: https://code.google.com/p/gmaps-api-issues/issues/detail?id=109
The point center of some localities I'm familiar with seem to be prominent landmarks, which I reckon are quite representative of what most people would think as "the center" of those cities:
The Spire, in Dublin (Ireland)
Puerta del Sol, in Madrid (Spain)
Others seem to have their center in a mere cross of main roads, as is the case in San Francisco and Zurich. Others, mostly in small towns, I can honestly not make sense of.
My take is that the center of a city or county only makes sense as a rough approximation of what people would point at as the downtown area, in a city, or where most people live, in an big unevenly/sparsely populated area. Such point would only be useful at a low zoom level.
This seems somewhat consistent with the idea that a city or a county does not really have a "center" as such, a single point where absolutely everybody would put the finger to say "here, is this is the heart of this city".
But even if/when there is such a point, it may not always be what you're looking for. For instance, if you're traveling between cities by train, you probably care not for such points, but rather care for their train stations.
Example: transit directions from San Jose to San Francisco return a route that starts at the San Jose Diridon Station (37.33068,-121.902382) and ends at the San Francisco Station (37.776687,-122.394857), because those are the relevant points for each city in this context.

Google Maps API missing alt_id

Here it says that any alternative place_id's will be returned in an array: https://developers.google.com/places/place-id#multiple-ids
Further documentation here and here shows that any alternative id's will be returned under alt_ids, as shown in the examples.
I tried this both through the browser and through the python googlemaps library, and neither were returned with alt_ids.
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJrTLr-GyuEmsRBfy61i59si0&key=YOUR_API_KEY
In fact, querying by the alt_id shown in the documentation as D9iJyWEHuEmuEmsRm9hTkapTCrk resulted in googlemaps.exceptions.ApiError: INVALID_REQUEST, or in the browser "status" : "INVALID_REQUEST":
https://maps.googleapis.com/maps/api/place/details/json?placeid=D9iJyWEHuEmuEmsRm9hTkapTCrk&key=YOUR_API_KEY
Google Places API's Support Page sent me here to StackOverflow, hope you guys can tell me about this oddity or if I'm mistaken about something.
JSON returned via browser:
{
"html_attributions" : [],
"result" : {
"address_components" : [
{
"long_name" : "5",
"short_name" : "5",
"types" : [ "floor" ]
},
{
"long_name" : "48",
"short_name" : "48",
"types" : [ "street_number" ]
},
{
"long_name" : "Pirrama Road",
"short_name" : "Pirrama Rd",
"types" : [ "route" ]
},
{
"long_name" : "Pyrmont",
"short_name" : "Pyrmont",
"types" : [ "locality", "political" ]
},
{
"long_name" : "New South Wales",
"short_name" : "NSW",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "Australia",
"short_name" : "AU",
"types" : [ "country", "political" ]
},
{
"long_name" : "2009",
"short_name" : "2009",
"types" : [ "postal_code" ]
}
],
"adr_address" : "5, \u003cspan class=\"street-address\"\u003e48 Pirrama Rd\u003c/span\u003e, \u003cspan class=\"locality\"\u003ePyrmont\u003c/span\u003e \u003cspan class=\"region\"\u003eNSW\u003c/span\u003e \u003cspan class=\"postal-code\"\u003e2009\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eAustralia\u003c/span\u003e",
"formatted_address" : "5, 48 Pirrama Rd, Pyrmont NSW 2009, Australia",
"formatted_phone_number" : "(02) 9374 4000",
"geometry" : {
"location" : {
"lat" : -33.8666113,
"lng" : 151.1958324
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "4f89212bf76dde31f092cfc14d7506555d85b5c7",
"international_phone_number" : "+61 2 9374 4000",
"name" : "Google",
"opening_hours" : {
"open_now" : false,
"periods" : [
{
"close" : {
"day" : 1,
"time" : "1730"
},
"open" : {
"day" : 1,
"time" : "0830"
}
},
{
"close" : {
"day" : 2,
"time" : "1730"
},
"open" : {
"day" : 2,
"time" : "0830"
}
},
{
"close" : {
"day" : 3,
"time" : "1730"
},
"open" : {
"day" : 3,
"time" : "0830"
}
},
{
"close" : {
"day" : 4,
"time" : "1730"
},
"open" : {
"day" : 4,
"time" : "0830"
}
},
{
"close" : {
"day" : 5,
"time" : "1700"
},
"open" : {
"day" : 5,
"time" : "0830"
}
}
],
"weekday_text" : [
"Monday: 8:30 AM – 5:30 PM",
"Tuesday: 8:30 AM – 5:30 PM",
"Wednesday: 8:30 AM – 5:30 PM",
"Thursday: 8:30 AM – 5:30 PM",
"Friday: 8:30 AM – 5:00 PM",
"Saturday: Closed",
"Sunday: Closed"
]
},
"photos" : [
{
"height" : 960,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/100919424873665842845/photos\"\u003eDonnie Piercey\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAU3wmS35nuxnOk2tcFwH3NYQMzwHLctqPA4phgAjWG8exKv_5m78v0UHmerSVmrzzIKE0tKfEdTqMcAHkTiLw0bWL-fyyvXoPAXRAotZg9wuKjH5fj8QdkhTmzCn2p7sMEhBlQG6P4kyofNlfThhN0TmfGhQQLs8LkCaO-U7CZmarOQsgj9C4gg",
"width" : 1280
},
{
"height" : 1365,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/105932078588305868215/photos\"\u003eMaksym Kozlenko\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAA0AvSogp7ZPWvnB2rsqm7FWOenJ1Z84NIkMyj2kOXEvpp3qa1fjY9fcwfosQSsvG-328VQEUurQ8sLWHL78XMv7g8IMIEfYGw1v53wCxbVpqZtIXV6IqUUrmA6eliwldEhCW4fXsJND4GrxdPhl3ef9aGhTByfDbEMusTc8VZaVUAfFH2Uvspg",
"width" : 2048
},
{
"height" : 2368,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/108508601154030859314/photos\"\u003eLeo Angelo George\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAA5oe21xN1_VMhXfZXgmPyVk9j_m37TkPPDahrdPrbl04QIoajmnyOcofgichznJECYOaznhlf1-A-GhN0czidtrNnPRtLwXBCf0_VBfaILeQoEpqnYm55yLCqrRaOP-QHEhDFNFZf-R-6ztgzE4buqqNqGhRj1jOU72hSaqO7flBhiP2oFg59ug",
"width" : 3200
},
{
"height" : 1131,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/105637462841200316207/photos\"\u003eFrom a Google User\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAA3--DtrTWRxZPA0g_Ej18bg9YBrT_iNP5UPC1KYuNk8zuvB11952cz2x1cyuD9gaPqIPchSjxkHalNlXBDKt3eO-Y7dWokIkPCbbbGmzEiCk80d3TCkpxPnW5NStk126uEhCgKTqcXZRddb3kNGHKPakBGhTo0vj7mVd20M5w0D1LkIsuY2AC6g",
"width" : 1600
},
{
"height" : 2184,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114701241123617315548/photos\"\u003eMargaret Lee\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAA-iZAmof-HPdfIAfxPPHlD2iL3SMlpFuZgZckDaV0ezo-rfX8ORzZA-DI2K6l0x0iJvMG6zkgXq8M027UqYu9QEBpvUqTZg4NEcPHu9CKRxI1sB0UqIL7bqhKrjiSm7HYEhCzVzvVoQnGkE4PDewcbSOyGhRQ0oLDDhDPlMSqqshawcK7YtSNew",
"width" : 2911
},
{
"height" : 1536,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/104177669626132953795/photos\"\u003eJustine OBRIEN\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAyW321TV_2ZCprgrGuc8FORmBKN4xc49DZDVtXBXS54zFfZJ0egb8e-BKRjh_yhLOWfR24xgJx7nrTW9kIIoGzC0RNINNKoLGqSU6htuydl0IhoN4dnyuybpNwOYRnAkpEhA01ud2Sig_MUSGCWP1U3wFGhR_IBXXAsi9qmSaCIDXz6CaNGCO2Q",
"width" : 2048
},
{
"height" : 608,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/116750797999944764767/photos\"\u003eJessica Pfund\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAADbRHDpuIqFe-m4vbLOcgTXjSuCb3O5oCUuIYz1brH1bJJ6J5SWPYZKcqLDfTy2SL_j02NNTkBVtts824pt8c3epQpxpZ2bw1y6fK0_N3GC8pX7ye9B_KUQfIFHbYRE83EhBSpMGzss4lmFjMXIvCnniiGhQjD1YrZjXt7ubRHbwBB4Xsqx3zGg",
"width" : 1080
},
{
"height" : 612,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114701241123617315548/photos\"\u003eMargaret Lee\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAANkWnV43a_uW2O0HiQrz9kS2OSIIedZc7wCMcTaG7uT8y8_5fQeLF-uHkm_Buu68FxclKVic4N8PYvvr8j0eb9nPSWdm6YDPGXrtceT1NvZruWQDg5cqcjGuSOnc85ftdEhCAjJspccx3PEo6ohdczK9gGhQdb8KFUahTpzGoFwwb0ahek2m2xA",
"width" : 816
},
{
"height" : 2322,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/107252953636064841537/photos\"\u003eWilliam Stewart\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAt8-2VEklpEuHu-S3j6WCb_bLCNoPrnuMIr9rjE7HGjx4W7kKUuqR_d7TW7uyG96yc5r986R830-TXlhkUcIlqtxR7bv3sGcLTrWOfwIhC0GpmJbC6Wv0ybPD-mnRohwwEhA5qURsC2Xtp8K7FweldZgIGhSCipPyqSfeAQIadRV0M0rCmCBoUQ",
"width" : 4128
},
{
"height" : 1224,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/102793072679802771755/photos\"\u003eKeith Denny\u003c/a\u003e"
],
"photo_reference" : "CmRdAAAAuQhV8wWw0kRb7MJdy6L46Fht0KfCPUEZwVlwONs_CiEng0IG5lsecycfT1WEm1a0Lqwe7NjpATMLf5RaR_GPDiPGsUCpuLZA2-q-dzOcH8P8OJfkkVM58PdTIithnNuXEhAzY4RXHTtOD8VgHQYnF_-8GhRRzjGakfekcq0Ge9u_iKshhHlFdQ",
"width" : 1632
}
],
"place_id" : "ChIJN1t_tDeuEmsRUsoyG83frY4",
"rating" : 4.4,
"reference" : "CmRaAAAARUnabgoDUbptx7jmkjMZFNyM0ho4QO3Q0OknonZMWW5r8ctfDbJgSMUhyXnBaGYsnE8kaap-1d0dP48iN61kc1ArzGAwjxQCnZKPePuInJ4uaVexmwPIZFXDk1LRu6sqEhCeQ4-Mk2lGOJ5RbAD71wkqGhT0MpaqpHHxQr6pulLi6pQ_799NNw",
"reviews" : [
{
"aspects" : [
{
"rating" : 3,
"type" : "overall"
}
],
"author_name" : "Justine OBRIEN",
"author_url" : "https://plus.google.com/104177669626132953795",
"language" : "en",
"profile_photo_url" : "//lh6.googleusercontent.com/-s6AzNe5Qcco/AAAAAAAAAAI/AAAAAAAAFTE/NvVzCuI-jMI/photo.jpg",
"rating" : 5,
"text" : "Google Sydney is located on Darling Island on the glorious Sydney Harbour in a prime position easy to get to for staff and visitors. The reception has an excellent fresh living wall and the staff are welcoming, pleasant and friendly, ready to assist you with bountiful information for all inquiries. All ready to *do the right thing* Always helping *Go Get IT*, the right information to *Gather IT*, from all the right places plus *Give IT* at all the right times to all the right people! \nGo Get Gather Give Google excellence personified at Google Sydney! Thanks Google Sydney!",
"time" : 1451482843
},
{
"aspects" : [
{
"rating" : 3,
"type" : "overall"
}
],
"author_name" : "Danielle Lonnon",
"author_url" : "https://plus.google.com/118257578392162991040",
"language" : "en",
"profile_photo_url" : "//lh5.googleusercontent.com/-laqORDSvktk/AAAAAAAAAAI/AAAAAAAApfw/hX9vqf6fJ2g/photo.jpg",
"rating" : 5,
"text" : "As someone who works in the theatre, I don't find the Google offices nerdy, I find it magical and theatrical. Themed rooms with useful props and big sets with unique and charismatic characters. You sure this isn't a theatre company? Oh no wait Google has money, while the performing art does not.",
"time" : 1425790392
},
{
"aspects" : [
{
"rating" : 3,
"type" : "overall"
}
],
"author_name" : "Josh Kingston",
"author_url" : "https://plus.google.com/116686571356940046569",
"language" : "en",
"profile_photo_url" : "//lh5.googleusercontent.com/-dN2o7SFZSeI/AAAAAAAAAAI/AAAAAAAAEDw/ya9vvWx-cVo/photo.jpg",
"rating" : 5,
"text" : "An Enlightened stronghold. Glyph hack those level 8 portals.",
"time" : 1451709974
},
{
"aspects" : [
{
"rating" : 3,
"type" : "overall"
}
],
"author_name" : "Lachlan Martin",
"author_url" : "https://plus.google.com/101767769287488554641",
"language" : "en",
"profile_photo_url" : "//lh6.googleusercontent.com/-TuBhQ6C9ViI/AAAAAAAAAAI/AAAAAAAACcY/3Web5Iqk6vg/photo.jpg",
"rating" : 5,
"text" : "The cool-aid here tastes amazing!!! ",
"time" : 1439790358
},
{
"aspects" : [
{
"rating" : 0,
"type" : "overall"
}
],
"author_name" : "Lyn Bayliss",
"author_url" : "https://plus.google.com/116677609452593302785",
"language" : "en",
"profile_photo_url" : "//lh5.googleusercontent.com/-7OYAbqKTsPo/AAAAAAAAAAI/AAAAAAAACDw/wkM_ex5cHXM/photo.jpg",
"rating" : 1,
"text" : "Google Sydney reception desk recorded messaging service is a shocker and doesn't align with the hipster, groovy Google that we all know and love.....blah!",
"time" : 1449715765
}
],
"scope" : "GOOGLE",
"types" : [ "point_of_interest", "establishment" ],
"url" : "https://maps.google.com/?cid=10281119596374313554",
"user_ratings_total" : 117,
"utc_offset" : 660,
"vicinity" : "5 48 Pirrama Road, Pyrmont",
"website" : "https://www.google.com.au/about/careers/locations/sydney/"
},
"status" : "OK"
}
JSON returned via Python library googlemaps:
{
'result':{
'types':[
'point_of_interest',
'establishment'
],
'name':'Google',
'icon':'https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png',
'url':'https://maps.google.com/?cid=10281119596374313554',
'formatted_address':'5, 48 Pirrama Rd, Pyrmont NSW 2009, Australia',
'scope':'GOOGLE',
'international_phone_number':'+61 2 9374 4000',
'address_components':[
{
'short_name':'5',
'types':[
'floor'
],
'long_name':'5'
},
{
'short_name':'48',
'types':[
'street_number'
],
'long_name':'48'
},
{
'short_name':'Pirrama Rd',
'types':[
'route'
],
'long_name':'Pirrama Road'
},
{
'short_name':'Pyrmont',
'types':[
'locality',
'political'
],
'long_name':'Pyrmont'
},
{
'short_name':'NSW',
'types':[
'administrative_area_level_1',
'political'
],
'long_name':'New South Wales'
},
{
'short_name':'AU',
'types':[
'country',
'political'
],
'long_name':'Australia'
},
{
'short_name':'2009',
'types':[
'postal_code'
],
'long_name':'2009'
}
],
'formatted_phone_number':'(02) 9374 4000',
'website':'https://www.google.com.au/about/careers/locations/sydney/',
'id':'4f89212bf76dde31f092cfc14d7506555d85b5c7',
'reference':'CmRaAAAAFwTQO5LeVNJc_sog-WaEcH4RjJySPbl4MRp6Qpt-bTbLhbqhE2qi4SuWNl3OvnQ7qUTnWxcwv9lMzv211uvLukLxJHZCBy8rvST9LddkearXrkBIEEy-TBsViGeKE1zQEhBS3YBx75-VlS4Kbsrs-g_gGhQIDybgoVneX_XCmrVEWZr7idNqtg',
'place_id':'ChIJN1t_tDeuEmsRUsoyG83frY4',
'opening_hours':{
'periods':[
{
'close':{
'time':'1730',
'day':1
},
'open':{
'time':'0830',
'day':1
}
},
{
'close':{
'time':'1730',
'day':2
},
'open':{
'time':'0830',
'day':2
}
},
{
'close':{
'time':'1730',
'day':3
},
'open':{
'time':'0830',
'day':3
}
},
{
'close':{
'time':'1730',
'day':4
},
'open':{
'time':'0830',
'day':4
}
},
{
'close':{
'time':'1700',
'day':5
},
'open':{
'time':'0830',
'day':5
}
}
],
'weekday_text':[
'Monday: 8:30 AM – 5:30 PM',
'Tuesday: 8:30 AM – 5:30 PM',
'Wednesday: 8:30 AM – 5:30 PM',
'Thursday: 8:30 AM – 5:30 PM',
'Friday: 8:30 AM – 5:00 PM',
'Saturday: Closed',
'Sunday: Closed'
],
'open_now':False
},
'reviews':[
{
'author_url':'https://plus.google.com/104177669626132953795',
'rating':5,
'language':'en',
'text':'Google Sydney is located on Darling Island on the glorious Sydney Harbour in a prime position easy to get to for staff and visitors. The reception has an excellent fresh living wall and the staff are welcoming, pleasant and friendly, ready to assist you with bountiful information for all inquiries. All ready to *do the right thing* Always helping *Go Get IT*, the right information to *Gather IT*, from all the right places plus *Give IT* at all the right times to all the right people! \nGo Get Gather Give Google excellence personified at Google Sydney! Thanks Google Sydney!',
'time':1451482843,
'profile_photo_url':'//lh6.googleusercontent.com/-s6AzNe5Qcco/AAAAAAAAAAI/AAAAAAAAFTE/NvVzCuI-jMI/photo.jpg',
'aspects':[
{
'rating':3,
'type':'overall'
}
],
'author_name':'Justine OBRIEN'
},
{
'author_url':'https://plus.google.com/118257578392162991040',
'rating':5,
'language':'en',
'text':"As someone who works in the theatre, I don't find the Google offices nerdy, I find it magical and theatrical. Themed rooms with useful props and big sets with unique and charismatic characters. You sure this isn't a theatre company? Oh no wait Google has money, while the performing art does not.",
'time':1425790392,
'profile_photo_url':'//lh5.googleusercontent.com/-laqORDSvktk/AAAAAAAAAAI/AAAAAAAApfw/hX9vqf6fJ2g/photo.jpg',
'aspects':[
{
'rating':3,
'type':'overall'
}
],
'author_name':'Danielle Lonnon'
},
{
'author_url':'https://plus.google.com/116686571356940046569',
'rating':5,
'language':'en',
'text':'An Enlightened stronghold. Glyph hack those level 8 portals.',
'time':1451709974,
'profile_photo_url':'//lh5.googleusercontent.com/-dN2o7SFZSeI/AAAAAAAAAAI/AAAAAAAAEDw/ya9vvWx-cVo/photo.jpg',
'aspects':[
{
'rating':3,
'type':'overall'
}
],
'author_name':'Josh Kingston'
},
{
'author_url':'https://plus.google.com/101767769287488554641',
'rating':5,
'language':'en',
'text':'The cool-aid here tastes amazing!!! ',
'time':1439790358,
'profile_photo_url':'//lh6.googleusercontent.com/-TuBhQ6C9ViI/AAAAAAAAAAI/AAAAAAAACcY/3Web5Iqk6vg/photo.jpg',
'aspects':[
{
'rating':3,
'type':'overall'
}
],
'author_name':'Lachlan Martin'
},
{
'author_url':'https://plus.google.com/116677609452593302785',
'rating':1,
'language':'en',
'text':"Google Sydney reception desk recorded messaging service is a shocker and doesn't align with the hipster, groovy Google that we all know and love.....blah!",
'time':1449715765,
'profile_photo_url':'//lh5.googleusercontent.com/-7OYAbqKTsPo/AAAAAAAAAAI/AAAAAAAACDw/wkM_ex5cHXM/photo.jpg',
'aspects':[
{
'rating':0,
'type':'overall'
}
],
'author_name':'Lyn Bayliss'
}
],
'adr_address':'5, <span class="street-address">48 Pirrama Rd</span>, <span class="locality">Pyrmont</span> <span class="region">NSW</span> <span class="postal-code">2009</span>, <span class="country-name">Australia</span>',
'rating':4.4,
'vicinity':'5 48 Pirrama Road, Pyrmont',
'photos':[
{
'width':1280,
'photo_reference':'CmRdAAAAAFGroRwnVSiIpPP8xt-PKnVfkwpIaUDLC5yqxqHzWUMD3fZpSMIyD6syDsGL3dkXWz7jrnnHxpkh3qCjbUfzB2F4DSH-JQLQ-qW4mZyojOOwlj8A1XVceduF0oEfgHqbEhDRYd7EhaRibtisKjGzs1nmGhQmEqwEtFnn7_y4yCRiYOXixeTwxw',
'html_attributions':[
'Donnie Piercey'
],
'height':960
},
{
'width':2048,
'photo_reference':'CmRdAAAADQKS7SyoBuHtwAaF0szY9NOnmQ0KkIalzeUA86SNlrx-R_b6NZ6uobTTvHAryZetdJomLeFVR-l26EcX2Imc6rdvaQHB8Pu9Ap8mi4HK4x9pyh2X28Xa41uds1rofT4AEhB5iJ7Xb1wfmukgWdUPU5qVGhS62mDgtN47W_1kkR-WrIzBYwHxrQ',
'html_attributions':[
'Maksym Kozlenko'
],
'height':1365
},
{
'width':3200,
'photo_reference':'CmRdAAAAV18AQpoPo4Jw3dbhRubQghJavXV_wRJAaJe7Lff9d4lmQdraNNdgpbuJMnhpCZxs7jYDJdnZmvfWz3zcata4n5Wog7Sxd0Nm3nlvaABwZgsUK9IlgyTJ_3FLaTikKceVEhAwbUgZ3g0YtU-wSr-6ogkAGhQDWSfaqadzmmOBrKvWpgpjzqyO7A',
'html_attributions':[
'Leo Angelo George'
],
'height':2368
},
{
'width':1600,
'photo_reference':'CmRdAAAAu4UwCSySN8VGZFtGOYDtr6TXuZ0CQt2_bujy9Npyfxsof-mNf-IX2Iz_YaMCid-VKvf8K2kuYwIXHUBi3WzdCxMRdW-hV27aeWMkmu2wjiJh_l-nBo8QYuCCaIlOzC1kEhDhtDOUfuioyKsPLU_KYzroGhRhJcNIx7rj1Q8k4avVKlvZonkHFQ',
'html_attributions':[
'From a Google User'
],
'height':1131
},
{
'width':2911,
'photo_reference':'CmRdAAAANHUF6JBhb2IUEpnNY7rDF5_UJPeRuQ6FwMYZ-UJ5qmxLqf5b1CNibRftoKjnZVJQW7Op_SfBWUzLKIYy3lRmRHqVwrPCWgAjK92DSK7IDWZ5ijBIu8Z_-WllzTFdvmV6EhDCyK0mVot5b9CaUztziYc5GhR1OTTEVxMBwhaYeJvPNgOeJakv_g',
'html_attributions':[
'Margaret Lee'
],
'height':2184
},
{
'width':2048,
'photo_reference':'CmRdAAAAxqCYgmnZwt1YF5TZ37vao33dVrJbJfX8MNpGQ_pZb3nTi8SXI907v8Hmx9XKvCO_8DKOMW9yyq3ZVHo6dP-0Mx8FwYdGrRG2pCmBdY5eJa0rVvP5iiDJUKRTCT2hbMvqEhA34C5_emCBRsL14DSxTT1GGhQhheE9tpLZfK8AgxTknrr_DbdWlw',
'html_attributions':[
'Justine OBRIEN'
],
'height':1536
},
{
'width':1080,
'photo_reference':'CmRdAAAA4RSz4_OW32m3stm_jZYdW2xsrnmD2SuPRLj1yuLPEZG2r0TEYd3kNFRJ28eNDzeg_qhDxNS8SGhmn6ccnIIf585ZpWCRZY8gVUktqLaYZP61HvzW5RUdsgI5sNG8Y10mEhCxK0QxYY9XBEkGUH_pkr1NGhSDDNP3vM2ZC8LSJR-O6CHwdwGrLQ',
'html_attributions':[
'Jessica Pfund'
],
'height':608
},
{
'width':816,
'photo_reference':'CmRdAAAAK_s9fda-27-_oNHZmal2ZOf7M1mOy2TSAuHhNdfI22nB5YYOA-74rACq6gy5ngnhxhAz9KYOw2DakpDWmyRNUILBTvWkKHpHELlN3VSaiMuol4X29m6poxcLDxz5WMyBEhD4Ay8isWujvhWccQjIe0LXGhSMwSqguFi0nOZfjze-GEgVyCG4uQ',
'html_attributions':[
'Margaret Lee'
],
'height':612
},
{
'width':4128,
'photo_reference':'CmRdAAAAnZCp1N3thzDBC1Rq_lPGSeZWov8X73HkiXksleEyr5RIVM0kDGdZw9SDdIgbl8BeViOJ_56Z-livqIeA5-e-Vsf-XS3YPLGedSYH5FagMJWUuEfZaT0alX6umSlsP2jDEhDNjWgWGfNTtt_u6EpKITptGhSbKwnSUnLjHvPBL9v0CGCIJiUCKQ',
'html_attributions':[
'William Stewart'
],
'height':2322
},
{
'width':1632,
'photo_reference':'CmRdAAAAIMFo_fZSTk4TUwIuWVA04gnERP-uJ0VGJkVmEgf1YdA8wCGR_NubiE7_al0-HH1ZVkwrCDRqa_dBIYH8rp4qqHgyUurT2hAA5xgJkB9Ceyp0umpZymiTwQbGGkx6E_ffEhBO8j4SKIKJEtfQ3hrgWWKLGhTzj4aOY2HE4fydC1-fJIsvrhCZRw',
'html_attributions':[
'Keith Denny'
],
'height':1224
}
],
'user_ratings_total':117,
'utc_offset':660,
'geometry':{
'location':{
'lng':151.1958324,
'lat':-33.8666113
}
}
},
'html_attributions':[
],
'status':'OK'
}
Unless you are using the Place Add feature, the alt_ids and scope fields are probably not of any use to you.
As the documentation says, alt_ids may be empty or not present. It then says:
The most likely reason for a place to have an alternative place ID is if your application adds a place and receives an application-scoped place ID, then later receives a Google-scoped place ID after passing the moderation process.
This is the case with the D9iJyWEHuEmuEmsRm9hTkapTCrk Place ID shown in the example:
"place_id" : "ChIJN1t_tDeuEmsRUsoyG83frY4",
"scope" : "GOOGLE",
"alt_ids" : [
{
"place_id" : "D9iJyWEHuEmuEmsRm9hTkapTCrk",
"scope" : "APP"
}
],
Note how D9iJyWEHuEmuEmsRm9hTkapTCrk has APP scope, not GOOGLE scope. That means it is a Place ID only usable by the app that added it (i.e. using API key from the same project in the Google Developers Console), which is why your details request for it fails.

Google auto complete places, Omit country name of users location from predictions

I am using google.maps.places.AutocompleteService(); to get query predictions. Is it possible to omit country name from the predictions list of users location. For eaxmple. if i am in united states, when i search for sanfransisco. It should not show United states (Country name) in predictions list. But if i search for location- delhi in india, it should show 'Delhi India'(country name).
Is this possible using this service or any other google api service.
Note that, i need list of suggestion, not something tied with a textfield.
Your help will be greatly appreciated.
This is not possible without manually processing the results. So after receiving the json data as a response, you need to check if the suggested country is the same as the user's country and if it is then do not display it in the textfield.
A JSON response looks like this: In the value field you can check the country and decide whether or not to display it by comparing it to the user's country that needs to be set somewhere in your App.
I believe the JSON response will be save in a List<HashMap<String, String>> So you can loop over it and omit the country.
{
"status": "OK",
"predictions" : [
{
"description" : "Paris, France",
"id" : "691b237b0322f28988f3ce03e321ff72a12167fd",
"matched_substrings" : [
{
"length" : 5,
"offset" : 0
}
],
"place_id" : "ChIJD7fiBh9u5kcRYJSMaMOCCwQ",
"reference" : "CjQlAAAA_KB6EEceSTfkteSSF6U0pvumHCoLUboRcDlAH05N1pZJLmOQbYmboEi0SwXBSoI2EhAhj249tFDCVh4R-PXZkPK8GhTBmp_6_lWljaf1joVs1SH2ttB_tw",
"terms" : [
{
"offset" : 0,
"value" : "Paris"
},
{
"offset" : 7,
"value" : "France"
}
],
"types" : [ "locality", "political", "geocode" ]
},
{
"description" : "Paris Avenue, Earlwood, New South Wales, Australia",
"id" : "359a75f8beff14b1c94f3d42c2aabfac2afbabad",
"matched_substrings" : [
{
"length" : 5,
"offset" : 0
}
],
"place_id" : "ChIJrU3KAHG6EmsR5Uwfrk7azrI",
"reference" : "CkQ2AAAARbzLE-tsSQPgwv8JKBaVtbjY48kInQo9tny0k07FOYb3Z_z_yDTFhQB_Ehpu-IKhvj8Msdb1rJlX7xMr9kfOVRIQVuL4tOtx9L7U8pC0Zx5bLBoUTFbw9R2lTn_EuBayhDvugt8T0Oo",
"terms" : [
{
"offset" : 0,
"value" : "Paris Avenue"
},
{
"offset" : 14,
"value" : "Earlwood"
},
{
"offset" : 24,
"value" : "New South Wales"
},
{
"offset" : 41,
"value" : "Australia"
}
],
...
Reference: https://developers.google.com/places/webservice/autocomplete#location_biasing