Swift 3 - SwiftyJSON string returning null - json

I am using SwiftyJSON to download JSON from Google Places API (the json is as below)
{
"html_attributions" : [],
"results" : [
"formatted_address" : "153A Main St, East Calder, Livingston EH53, United Kingdom",
"geometry" : {
"location" : {
"lat" : 55.8959462,
"lng" : -3.4622283
},
"viewport" : {
"northeast" : {
"lat" : 55.8973141302915,
"lng" : -3.460921669708497
},
"southwest" : {
"lat" : 55.8946161697085,
"lng" : -3.463619630291501
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/shopping-71.png",
"id" : "4e89b3f89f67b043ec79e7dcb5574489bae409f7",
"name" : "Ink Well Tattoo Studio",
"opening_hours" : {
"exceptional_date" : [],
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 443,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/112667948691916642485/photos\"\u003eRobert Herschell\u003c/a\u003e"
],
"photo_reference" : "CoQBdwAAAElNWvg4vO6E6HvU2srxmeI4gDd-qIS9wXPkm_0CFgJ9ctzQTUeCRKJI-0GTajrBcy9UIJo0DdtRN-T2LgyRRm6G1VwaN7zyQSlbz-tadjMB6SmPQA1hSdTjdcwC3s3vlr72AGK8mwlkBI8-z_UYu7T915TXVESaI2_cRw3rs_woEhCzOzky--6PJ-bAqYM401HIGhSKbGY7dLvJxhqG9-Z7SmQIxBV4uQ",
"width" : 450
}
],
"place_id" : "ChIJudHXfnjbh0gRxikhSbbkZzU",
"rating" : 5,
"reference" : "CmRRAAAAbgLWU0cl7tbE04cc4VyHf7407xXydh88Ld3R2B1Kq9TIfOC2XHjXIM8BmKkhx_WS2YkA6cVHmSESrx8SGbAw0vpfcFchcEyQOaHEJqc-iY4d3UWvlEWw4DmbaOzyAyBtEhBC4X_b7g-qGcvcRDzEv3WIGhRYMy0MbZUaUqTYWGIy_JWDrfJECg",
"types" : [ "store", "point_of_interest", "establishment" ]
}
]
and i am able to get the address and name from each result in the JSON using SwiftyJSON and populate my table
let row = (indexPath as NSIndexPath).row
cell?.lblShopTitle.text = self.json["results"][row]["name"].string
however i am trying to get the photo_reference string and i cannot seem to access it as it continually comes back as null
let imgRef = self.json["results"][row]["photos"]["photo_reference"]

Please read the JSON carefully.
[] represents an array.
{} represents a dictionary.
Therefore the object for key photos is an array. So it's most likely
let imgRef = self.json["results"][row]["photos"][0]["photo_reference"]

Related

Google maps details API does not return fields

I am trying to retrieve information from the google maps place detail api.
I am calling this url:
https://maps.googleapis.com/maps/api/place/details/json?key=my_api_key&place_id=ChIJgQlGoRzcQUcRP8UPrtI8hcc&fields=geometry,price_level,rating,review,user_ratings_total
The place id comes from the Place Search api, it is the id of this place.
So I am requesting the following fields in the url: geometry, price level, rating, review, user_ratings_total, and my response is the following:
{
"html_attributions" : [],
"result" : {
"geometry" : {
"location" : {
"lat" : 47.510746,
"lng" : 19.036858
},
"viewport" : {
"northeast" : {
"lat" : 47.51209583029149,
"lng" : 19.0382836802915
},
"southwest" : {
"lat" : 47.50939786970849,
"lng" : 19.0355857197085
}
}
}
},
"status" : "OK"
}
Geometry is showing up all right, but the other fields are not.
According to the documentation, they are all valid query parameters and the parameters should be separated by a comma.
There are three types of fields in the documentation, all Basic type fields are working, the other two Contact and Atmosphere are not.
What do I do to get all the field parameters in the response?
It looks like you have the wrong place_id. The place_id you're using doesn't return the business you link to.
Using the Place ID Finder for BlackBelt Technology Kft gives a place_id of: ChIJUxteJqfeQUcRAXhmxC6DVn0
Using that place_id in your query returns the correct rating, reviews and user_ratings_total:
https://maps.googleapis.com/maps/api/place/details/json?key=[yourkey]&place_id=ChIJUxteJqfeQUcRAXhmxC6DVn0&fields=geometry,price_level,rating,review,user_ratings_total
returns:
{
"html_attributions" : [],
"result" : {
"geometry" : {
"location" : {
"lat" : 47.510746,
"lng" : 19.036858
},
"viewport" : {
"northeast" : {
"lat" : 47.51209583029149,
"lng" : 19.0382836802915
},
"southwest" : {
"lat" : 47.50939786970849,
"lng" : 19.0355857197085
}
}
},
"rating" : 4.9,
"reviews" : [
{
"author_name" : "Ferenc Magnucz",
"author_url" : "https://www.google.com/maps/contrib/106293318482835037880/reviews",
"language" : "hu",
"profile_photo_url" : "https://lh6.ggpht.com/-iV81elgPTlY/AAAAAAAAAAI/AAAAAAAAAAA/UtxhI3d0Hc0/s128-c0x00000000-cc-rp-mo/photo.jpg",
"rating" : 5,
"relative_time_description" : "a year ago",
"text" : "Profi fejlesztők.",
"time" : 1523996058
},
{
"author_name" : "Balázs Solti",
"author_url" : "https://www.google.com/maps/contrib/106041701773835494953/reviews",
"language" : "hu",
"profile_photo_url" : "https://lh5.ggpht.com/-yE-3lI1u9vo/AAAAAAAAAAI/AAAAAAAAAAA/cXsW4d_QR3Q/s128-c0x00000000-cc-rp-mo-ba5/photo.jpg",
"rating" : 5,
"relative_time_description" : "a year ago",
"text" : "Családias, kellemes iroda tele jó emberekkel",
"time" : 1511865164
},
{
"author_name" : "Norbert Csaba Herczeg",
"author_url" : "https://www.google.com/maps/contrib/117379994807862656830/reviews",
"profile_photo_url" : "https://lh3.ggpht.com/-i2x74XtvUJM/AAAAAAAAAAI/AAAAAAAAAAA/ko28SV_gxG4/s128-c0x00000000-cc-rp-mo/photo.jpg",
"rating" : 5,
"relative_time_description" : "a year ago",
"text" : "",
"time" : 1513607989
},
{
"author_name" : "Tibor Dr. Szállási",
"author_url" : "https://www.google.com/maps/contrib/107869538624149315782/reviews",
"profile_photo_url" : "https://lh4.ggpht.com/-6_bNC24Uwfc/AAAAAAAAAAI/AAAAAAAAAAA/XCbaj4_6gak/s128-c0x00000000-cc-rp-mo-ba3/photo.jpg",
"rating" : 5,
"relative_time_description" : "a year ago",
"text" : "",
"time" : 1513852229
},
{
"author_name" : "Tamas Molnar",
"author_url" : "https://www.google.com/maps/contrib/106716196386208549131/reviews",
"profile_photo_url" : "https://lh5.ggpht.com/-CbTBYAV3R2o/AAAAAAAAAAI/AAAAAAAAAAA/DeIEdrGy8gs/s128-c0x00000000-cc-rp-mo/photo.jpg",
"rating" : 5,
"relative_time_description" : "11 months ago",
"text" : "",
"time" : 1540533991
}
],
"user_ratings_total" : 35
},
"status" : "OK"
}
It does not return a price level, presumably because that data does not exist for this business (it doesn't appear to be a restaurant/bar/cafe)
A business (in the Places API) will have the business name in its entry, as well as the address. The entries for the addresses won't.
PlaceId: ChIJgQlGoRzcQUcRP8UPrtI8hcc
Is the address: Budapest, Királyfürdő u. 4, 1027 Hungary
Not the business: BlackBelt Technology Kft. at the address: Budapest, Királyfürdő u. 4, 1027 Hungary
If I use the Place ID Finder
I get a PlaceId of ChIJUxteJqfeQUcRAXhmxC6DVn0,
Which has the fields you are looking for.
proof of concept fiddle

Invalid Places Request

I am sending a request like this:
https://maps.googleapis.com/maps/api/place/search/json?radius=30&location=37.7858742105946,-122.406341359019&rankby=distance&key=MYKEYHERE&type=establishment
But the response is coming back as this:
{
"html_attributions" : [],
"results" : [],
"status" : "INVALID_REQUEST"
}
What is wrong about my request that is causing it to be invalid?
From the documentation:
radius — Defines the distance (in meters) within which to return place results. The maximum allowed radius is 50 000 meters. Note that radius must not be included if rankby=distance (described under Optional parameters below) is specified.
Remove rankby=distance from the request (for a 30 meter radius, it doesn't make sense).
https://maps.googleapis.com/maps/api/place/search/json?radius=30&location=37.7858742105946,-122.406341359019&key=<KEY>&type=establishment
Gives me this response:
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : 37.7860877,
"lng" : -122.4064646
},
"viewport" : {
"northeast" : {
"lat" : 37.7874464802915,
"lng" : -122.4050379197085
},
"southwest" : {
"lat" : 37.7847485197085,
"lng" : -122.4077358802915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/shopping-71.png",
"id" : "acf15a7460a5b2a3c8f7bba1af978fb2fc744f0d",
"name" : "A/X Armani Exchange",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"place_id" : "ChIJZyuhr4iAhYARpQEX4hwEJQI",
"rating" : 4.1,
"reference" : "CmRRAAAAMfTprFXJRaU_yLIqTAeIcGTxQ_6S2eYtBeRTwKk_7Pl6yXePzu3fNbz1gsEyTGEE_l8k_iW7VPjjpL34ynxSdzti1ivWeFQds_m9UD7cEqTuIldgqnT-46iySaeTEdMtEhBCcM7tqTnT5B_4a7gnK81cGhRJKFvJGTM33KhWHKUlrZ6xN7TuEQ",
"scope" : "GOOGLE",
"types" : [ "clothing_store", "store", "point_of_interest", "establishment" ],
"vicinity" : "25 Stockton Street, San Francisco"
}
],
"status" : "OK"
}

Google Geocoding API always returns a lat long from centre of UK, no matter what search term we use

We've been using this API from quite some time. We could see addresses being returned out of the UK & hence changed the geocoding URL to restrict to UK only.
http://maps.googleapis.com/maps/api/geocode/xml?latLng=54,-2&address=gdfgsdgsd,GB
http://maps.googleapis.com/maps/api/geocode/xml?latLng=54,-2&address=gdfgsdgsd,GB&components=country:GB
Please check the results for both of the above URL's.
The first URL returns ZERO_RESULTS which is correct.
The second one always returns a lat long from centre of UK, no matter what search term we use.
You can also try replacing the value for 'address' to replicate the issue :
452376452334,^$%^$%^$%,458352462354^$%^$%^
As per the Google Geocoding API about Component Filtering
A query containing a component filter will only return the geocoding
results that match the filter. If no matches are found, the geocoder
will return a result that matches the filter itself.
Request :
https://maps.googleapis.com/maps/api/geocode/json?address=someincomprehesibleaddress&components=administrative_area:TX|country:US&key=YOUR_API_KEY
{
"results" : [
{
"address_components" : [
{
"long_name" : "Texas",
"short_name" : "TX",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "Texas, USA",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 36.5007041,
"lng" : -93.5080389
},
"southwest" : {
"lat" : 25.8371638,
"lng" : -106.6456461
}
},
"location" : {
"lat" : 31.9685988,
"lng" : -99.9018131
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 36.5015087,
"lng" : -93.5080389
},
"southwest" : {
"lat" : 25.8371638,
"lng" : -106.6456461
}
}
},
"partial_match" : true,
"place_id" : "ChIJSTKCCzZwQIYRPN4IGI8c6xY",
"types" : [ "administrative_area_level_1", "political" ]
}
],
"status" : "OK"
}
Component filtering will return a ZERO_RESULTS response only if you provide filters that exclude each other.
Request :
https://maps.googleapis.com/maps/api/geocode/json?components=administrative_area:TX|country:FR&key=YOUR_API_KEY
{
"results" : [],
"status" : "ZERO_RESULTS"
}
Looks like I have found a way to resolve this.
The URL pattern I use now is :
http://maps.googleapis.com/maps/api/geocode/xml?address=Leeds,UK|GB
The below URL now gives ZERO_RESULTs
http://maps.googleapis.com/maps/api/geocode/xml?address=gdfgsdgsd,UK|GB
Also as Joyson suggested, we could also check for the country returned back & display an error message.

DirectionsService.Route - try to acces lat, lng not working

From a DestinationsService.Route response I would like to access the lat and lng values like the following:
var latitude0 = routes[0].legs[0].steps[0].start_location.lat;
var longitude0 = routes[0].legs[0].steps[0].start_location.lng;
console.log("var ["+latitude0+","+longitude0+"]");
Viewing the DestinationsService.Route with the Firefox debugger the json response looks like the following:
"routes" : [
{
"bounds" : {...}
},
"copyrights" : "Map data ©2015 Google",
"legs" : [
{
"distance" : {...},
"duration" : {...},
"end_address" : "something",
"end_location" : {...},
"start_address" : "another thing",
"start_location" : {...},
"steps" : [
{
"distance" : {...},
"duration" : {
"text" : "2 mins",
"value" : 104
},
"end_location" : {
"lat" : 14.64548629999999,
"lng" : 21.0152624
},
"html_instructions" : "...",
"polyline" : {
"points" : "..."
},
"start_location" : {
"lat" : 14.64537809999999,
"lng" : 17.9754639
},
"travel_mode" : "DRIVING"
I can access all other fields and values within the steps[0], e.g.
routes[0].legs[0].steps[0].travel_mode
which gives me "DRIVING" or
routes[0].legs[0].steps[0].duration.text
which gives me "2 mins".
But when accessing as explained in the beginning lat and lng of start_location or end_location it gives me (which is the console print-out):
var [function (){"use strict"; return a},function (){"use strict";return b}]
What am I doing wrong?
Thanks in advance for your help.
The google.maps.LatLng object has lat/lng methods, you need to call them to get the appropriate value. Instead of:
var latitude0 = routes[0].legs[0].steps[0].start_location.lat;
var longitude0 = routes[0].legs[0].steps[0].start_location.lng;
Do:
var latitude0 = routes[0].legs[0].steps[0].start_location.lat();
var longitude0 = routes[0].legs[0].steps[0].start_location.lng();
working fiddle

Google Api Route Without Steps

One question for google api route
I wanted to know if it is possible to make a request to the google just getting the timing and duration of the full path without receiving each of the intermediate steps
thanks
http://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&sensor=false
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 45.51014580,
"lng" : -73.55252489999999
},
"southwest" : {
"lat" : 43.65331030,
"lng" : -79.38373319999999
}
},
"copyrights" : "Datos de mapa ©2013 Google",
"legs" : [
{
"distance" : {
"text" : "542 km",
"value" : 542385
},
"duration" : {
"text" : "5h 14 min",
"value" : 18834
},
"end_address" : "Montreal, Quebec, Canadá",
"end_location" : {
"lat" : 45.50857120,
"lng" : -73.55376740
},
"start_address" : "Toronto, Ontario, Canadá",
"start_location" : {
"lat" : 43.65331030,
"lng" : -79.38276750
},
Use the DistanceMatrix API
The Google Distance Matrix API is a service that provides travel distance and time for a matrix of origins and
destinations. The information returned is based on the recommended route between start and end points, as calculated
by the Google Maps API, and consists of rows containing duration and distance values for each pair.
http://maps.googleapis.com/maps/api/distancematrix/json?origins=Toronto&destinations=Montreal&sensor=false
(Note the parameters: origins and destinations (plural form, unlike the directions api)
{
"destination_addresses" : [ "Montreal, QC, Canada" ],
"origin_addresses" : [ "Toronto, ON, Canada" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "542 km",
"value" : 542384
},
"duration" : {
"text" : "5 hours 14 mins",
"value" : 18835
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}