Append multiple NSMutableArray data to another NSMutableArray in swift 3 - ios

Let's say, there is shipping nsdictionary value is required to send to server, and there is items NSMutableArray inside shipping and, again there is sub-items NSMutableArray inside items.
That's why I've coded like that:
for cake in cakes {
for item in cakeItemsOpt {
let optionalItem = [
"item_req_mod_p_id": item.cakeItemModId,
"l_req_mod_p_id": item.cakeModId,
"mod_id": item.cakeModId,
"mod_qty": item.cakeQty
]
itemsOptional.add(optionalItem)
}
for item in cakeItemsReq {
let requiredItem = [
"item_req_mod_p_id": item.cakeItemModId,
"l_req_mod_p_id": item.cakeModId,
"mod_id": item.cakeModId,
"mod_qty": "1"
]
itemsRequired.add(requiredItem)
}
let cakeParam: NSDictionary = [
"id": cake.cakeId,
"qty": cake.cakeQty,
"type": cake.cakeType,
"name": cake.cakeName,
"image": cake.cakeImage,
"req_modifiers": itemsRequired,
"opt_modifiers": itemsOptional
]
items.add(cakeParam)
}
let param: NSDictionary = [
"user_id": user_id,
"token": token,
"delivery": "del",
"delivery_remark": delivery_remark,
"delivery_date": delivery_date,
"delivery_time": delivery_time,
"delivery_charge": delivery_charge,
"item": items,
"payment_method_id": payment_id,
] as [String : Any]
param is main object to send to server.
But the result is not what I've expected,
["delivery_remark": "heavy", "payment_method_id": "4", "delivery": "del", "token": "0l8BwedwkZQltcFYFhCpicQZeQOhikyYLxa8R3u2", "item": <__NSArrayM 0x60800044ea90>(
{
id = 11;
image = "";
name = "Red Velvet 16cm";
"opt_modifiers" = (
{
"item_req_mod_p_id" = 49;
"l_req_mod_p_id" = 3;
"mod_id" = 3;
"mod_qty" = "";
},
{
"item_req_mod_p_id" = 49;
"l_req_mod_p_id" = 4;
"mod_id" = 4;
"mod_qty" = "";
}
);
qty = 2;
"req_modifiers" = (
{
"item_req_mod_p_id" = 55;
"l_req_mod_p_id" = 8;
"mod_id" = 8;
"mod_qty" = 1;
},
{
"item_req_mod_p_id" = 56;
"l_req_mod_p_id" = 3;
"mod_id" = 3;
"mod_qty" = 1;
}
);
"run_no" = "6260-1c86";
"small_candles" = "";
"sponge_color_id" = "";
"theme_id" = "";
"theme_name" = "";
type = item;
"word_color_id" = "";
}
)
, "delivery_charge": "15.00", "user_id": "21", "delivery_time": "3", "delivery_date": "2017-02-27"]
There is <__NSArrayM 0x60800044ea90> included in my object. Please let me know how to correct my coding to get correct result. Thanks.

Then i guess you want something like
let data: [String : [String : [String : [String]]]]
data = [
"shipping" : ["items" : ["subitemKey" : ["subitemArray"]]]
]
So you have a dictionary that contains a dictionary for a key "shipping" that contains a dictionary for key "items" that contains arrays for keys of different subitems

Related

Swift: Unwrapping a dictionary messes up the order of the values inside of it

I am receiving JSON which then I'm storing in a dictionary variable menus. However, the problem is after unwrapping the data, the order of the "menus" gets messed up. And so they do not get displayed in order in the UI.
print("INSIDE CMSessionManger.login result[menus]: ", result["menus"]!)
/*
INSIDE CMSessionManger.login result[menus]: {
1 = {
id = 1;
label = Accueil;
maxNumberPerPage = 20;
};
2 = {
id = 2;
label = "Mes favoris";
maxNumberPerPage = 20;
};
3 = {
id = 3;
label = "Les s\U00e9lections";
maxNumberPerPage = 20;
};
4 = {
id = 4;
label = "Acc\U00e8s illimit\U00e9";
maxNumberPerPage = 20;
};
}
**/
print("INSIDE CMSessionManger.login type(of: result[menus]!: ", type(of: result["menus"]!))
if let menus = result["menus"] as? [String: Any]{
print("INSIDE CMSessionManger.login Setting menus")
print("INSIDE CMSessionManger.login menus: ", menus)
/*
INSIDE CMSessionManger.login menus: ["2": {
id = 2;
label = "Mes favoris";
maxNumberPerPage = 20;
}, "4": {
id = 4;
label = "Acc\U00e8s illimit\U00e9";
maxNumberPerPage = 20;
}, "1": {
id = 1;
label = Accueil;
maxNumberPerPage = 20;
}, "3": {
id = 3;
label = "Les s\U00e9lections";
maxNumberPerPage = 20;
}]
**/
}
I really don't understand why would a simple unwrap change the order of the dictionary values.
Dictionaries are unordered collections. There is no way to guarantee that you will get the items back in the same order in which you add them. It looks like your keys are numbers, and are repeated in the "id" key/value pair of each dictionary entry. If you really want the data to have a specific order, why not send the items in an array?
You could use the Dictinary.values property to get the entries in your dictionary into an array, and then sort those entries by their id values.
Here is sample code that does that:
let aDict:[Int: [String:Any]] = [
1 :
["id": 1,
"label": "Accueil",
"maxNumberPerPage":20 ],
2 : ["id": 2,
"label": "Mes favoris",
"maxNumberPerPage": 20
],
3 : ["id": 3,
"label": "Les sélections",
"maxNumberPerPage": 20
]
]
let values = aDict.values.sorted{
($0["id"] as! Int) < ($1["id"] as! Int) }
values.forEach {print($0)}
Note that the code above will crash if the contents of any of the inner dictionaries does not contain a key/value pair with the key "id" and with a value that is an Int. Production code that parsed JSON would need input validation.

Json Parsing in swift 4.2 using Codable

I am working on one project.I got one response from API.Now I want to fetch that response through JsonDecode().decod funcion with structure using decodable class.
I have made codable structure but it gives me error like :
The data couldn’t be read because it isn’t in the correct format.
My API Response is:
{
auth = 1;
data = {
"dealer_rating" = {
average = "3.5";
"average_width" = "70%";
count = 2;
dislikes = 0;
likes = 2;
rate1 = 4;
"rate1_label" = "Atenci\U00f3n al cliente";
"rate1_width" = "80%";
rate2 = "3.5";
"rate2_label" = "Proceso de compra";
"rate2_width" = "70%";
rate3 = 3;
"rate3_label" = "Experiencia general";
"rate3_width" = "60%";
};
review = (
{
average = 3;
"post_author" = 16;
"post_content" = "Test of iOS developer.";
"post_title" = "iOS Test";
rate1 = 3;
"rate1_label" = "Atenci\U00f3n al cliente";
rate2 = 3;
"rate2_label" = "Proceso de compra";
rate3 = 3;
"rate3_label" = "Experiencia general";
"stm_recommended" = yes;
username = "";
},
{
average = 4;
"post_author" = 22;
"post_content" = vvvvvvvvvv;
"post_title" = vvvvvvvvvv;
rate1 = 5;
"rate1_label" = "Atenci\U00f3n al cliente";
rate2 = 4;
"rate2_label" = "Proceso de compra";
rate3 = 3;
"rate3_label" = "Experiencia general";
"stm_recommended" = yes;
username = Vnn;
}
);
};
message = "Review found.";
status = 1;
}
My Decodable Structure is :
struct resDelerReview : Codable {
struct struDataString : Codable {
var average:String?
var rate1:Int
var rate1_label:String?
var rate2:Int
var rate2_label:String?
var rate3:Int
var rate3_label:String?
var likes:Int
var dislikes:Int
var count:Int
var rate1_width:String?
var rate2_width:String?
var rate3_width:String?
var average_width:String?
}
struct struReviewList : Codable {
var post_author:String?
var username:String?
var post_content:String?
var post_title:String?
var rate1:String?
var rate1_label:String?
var rate2:String?
var rate2_label:String?
var rate3:String?
var rate3_label:String?
var stm_recommended:String?
var average:Int
}
struct reviewRating : Codable {
let dealer_rating:struDataString
let review:[struReviewList]
}
let data:reviewRating
let status:Bool
let auth:Bool
let message:String?
}
Postman response in text
{
"data": {
"dealer_rating": {
"average": "3.5",
"rate1": 4,
"rate1_label": "Atención al cliente",
"rate2": 3.5,
"rate2_label": "Proceso de compra",
"rate3": 3,
"rate3_label": "Experiencia general",
"likes": 2,
"dislikes": 0,
"count": 2,
"rate1_width": "80%",
"rate2_width": "70%",
"rate3_width": "60%",
"average_width": "70%"
},
"review": [
{
"post_author": "16",
"username": "",
"post_content": "Test of iOS developer.",
"post_title": "iOS Test",
"rate1": "3",
"rate1_label": "Atención al cliente",
"rate2": "3",
"rate2_label": "Proceso de compra",
"rate3": "3",
"rate3_label": "Experiencia general",
"stm_recommended": "yes",
"average": 3
},
{
"post_author": "22",
"username": "Vnn",
"post_content": "vvvvvvvvvv",
"post_title": "vvvvvvvvvv",
"rate1": "5",
"rate1_label": "Atención al cliente",
"rate2": "4",
"rate2_label": "Proceso de compra",
"rate3": "3",
"rate3_label": "Experiencia general",
"stm_recommended": "yes",
"average": 4
}
]
},
"status": true,
"auth": true,
"message": "Review found."
}
My Postman Response is:
Please help me guys I am getting stuck.
Thanks in advance
The error is quite clear if you read the whole of it, it is the property rate2 that is declared as an Int but contains 3.5 for one of the elements
So change it in the struDataString struct to
var rate2: Double
Note There are several other similar fields like rate2 in the struDataString and those are very likely that they may contain double values to like the other rateX fields. You might want to check out the documentation for all of them

Read out specific JSON from NSArray

This is the JSON object I'm getting from the openweathermap - API:
["main": {
humidity = 12;
pressure = 922;
temp = "271.13";
"temp_max" = "171.15";
"temp_min" = "291.15";
}, "name": mycity, "id": 299129219, "coord": {
lat = "92.1211";
lon = "182.1211";
}, "weather": <__NSArrayI 0x1c042e820>(
{
description = "light snow";
icon = 13n;
id = 120;
main = Snow;
},
{
description = mist;
icon = 50n;
id = 722;
main = Mist;
}
)
, "clouds": {
all = 12;
}, "dt": 211, "base": stations, "sys": {
country = XXX;
id = 4891;
message = "0.02221";
sunrise = 1221122112;
sunset = 4343344343;
type = 1;
}, "cod": 100, "visibility": 3200, "wind": {
speed = 3;
}]
Because I like to readout some information (like the current temperature, the weather description, etc.) I tried to use this few lines:
let temperature = (result["main"] as! [String:Double])["temp"]!
The code above is working fine but I got massive problems reading out the description of the first Weather element (called "light snow"):
let description = (result["weather"] as! [String:Any]).first["description"]! //(result should be : "light snow")
... doesn't seems working at all.
So how can I fix this issue?
Thanks a million in advance.
Also used this API :)
This worked for me:
guard let weathersArray = json["weather"] as? [[String: Any]],
let weatherJson = weathersArray.first,
let description = weatherJson["description"] as? String
else { return }
Update: in case you want all the array elements just loop over the weathersArray and get all the descriptions.

How do I sort data in Firebase?

so I try to sort data from with most likes to the least. How do I do that if don't have an object name? because currently I only have the ID of the object?
here's my Firebase json:
["-KfSODzRPjy46ayCFRBH": {
"_createdAt" = 1489773065234;
"_updatedAt" = 1489773065234;
content = (
"<null>",
Tittle,
"why not there is the nnnd ksksks lalalalalkdkdkdkdk kadsjfakl;",
whhhhhhalalallala
);
imageTitle = 1489773064177;
like = 2;
title = "Third Post";
},
["-KfSODzRPjy46ayCFRBH": {
"_createdAt" = 1489773065234;
"_updatedAt" = 1489773065234;
content = (
"<null>",
Tittle,
"why not there is the nnnd ksksks lalalalalkdkdkdkdk kadsjfakl;",
whhhhhhalalallala
);
imageTitle = 1489773064177;
like = 3;
title = "Third Post";
},
this is how I read:
let handleref = databaseRef.child("v1/postmodel").observe(.value, with: { (snapshot) in
let postDict = snapshot.value as! [String : AnyObject]
print(postDict)
})

iOS Swift - Google Place API (Web) returns JSON in a strange format

I'm building an iOS app in Swift 3 and I'm using Google Places API to get places data. I'm using the iOS API to get most of the data I need. But I also need to get the opening times which aren't (yet) provided by the iOS API.
So I have to query the web API to get that information. The request side of things is working fine, however, once I get the result and I turn it into JSON with JSONSerialisationand then print the output in the console, the format of this JSON is strange and I'm struggling to parse it.
When I paste that into a JSON reader it says it's invalid.
Here is the JSON that looks strange to me with these "(" and "=":
["html_attributions": <__NSArray0 0x17001ccf0>(
)
, "result": {
"address_components" = (
{
"long_name" = 611;
"short_name" = 611;
types = (
"street_number"
);
},
{
"long_name" = "Post Street";
"short_name" = "Post St";
types = (
route
);
},
{
"long_name" = "Lower Nob Hill";
"short_name" = "Lower Nob Hill";
types = (
neighborhood,
political
);
},
{
"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
);
},
{
"long_name" = 94109;
"short_name" = 94109;
types = (
"postal_code"
);
}
);
"adr_address" = "<span class=\"street-address\">611 Post St</span>, <span class=\"locality\">San Francisco</span>, <span class=\"region\">CA</span> <span class=\"postal-code\">94109</span>, <span class=\"country-name\">USA</span>";
"formatted_address" = "611 Post St, San Francisco, CA 94109, USA";
"formatted_phone_number" = "(415) 817-1391";
geometry = {
location = {
lat = "37.7877411";
lng = "-122.4120067";
};
viewport = {
northeast = {
lat = "37.78791149999999";
lng = "-122.4119977";
};
southwest = {
lat = "37.7876843";
lng = "-122.4120337";
};
};
};
icon = "https://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png";
id = 6a6d8b640d5260886eac5ce1b3aa73b3b0d0bb1c;
"international_phone_number" = "+1 415-817-1391";
name = "Joy's Place";
"opening_hours" = {
"open_now" = 1;
periods = (
{
close = {
day = 1;
time = 0000;
};
open = {
day = 0;
time = 0800;
};
},
{
close = {
day = 2;
time = 0000;
};
open = {
day = 1;
time = 0700;
};
},
{
close = {
day = 3;
time = 0000;
};
open = {
day = 2;
time = 0700;
};
},
{
close = {
day = 4;
time = 0000;
};
open = {
day = 3;
time = 0700;
};
},
{
close = {
day = 5;
time = 0000;
};
open = {
day = 4;
time = 0700;
};
},
{
close = {
day = 6;
time = 0000;
};
open = {
day = 5;
time = 0700;
};
},
{
close = {
day = 0;
time = 0000;
};
open = {
day = 6;
time = 0800;
};
}
);
"weekday_text" = (
"Monday: 7:00 am \U2013 12:00 am",
"Tuesday: 7:00 am \U2013 12:00 am",
"Wednesday: 7:00 am \U2013 12:00 am",
"Thursday: 7:00 am \U2013 12:00 am",
"Friday: 7:00 am \U2013 12:00 am",
"Saturday: 8:00 am \U2013 12:00 am",
"Sunday: 8:00 am \U2013 12:00 am"
);
};
photos = (
{
height = 3024;
"html_attributions" = (
"Kathleen S"
);
"photo_reference" = "CoQBdwAAAFE8a_M5quVcX6frenilHEFVXTycrrhj5R3MoS5sd_vKG1Gj46aJVAvVl_a4HVcPS4G5Z2JS00Pugdegn4is9KSfwIw6IoMNBL1zo3hK2dQjfArUezH9wfSYpNJCNzi4bUO6EesC4bT74B1-hzM6Us4gzKpLLAfImaF3VTeRX-SGEhCLAqUUWZsgueYvTkx8mEi8GhRCDxXbJR-ddaQFwJizvZIKa4EYKA";
width = 4032;
},
{
height = 3024;
"html_attributions" = (
"Jake Lim"
);
"photo_reference" = "CoQBdwAAANPkBrIvYxn3UrYliLvLgk3Z4tOmS_twOv9nbMSTFmAR00Mff8XCMWQRUeigOYw1dSheyerBgimteHAHdRMzTCAWkJ7V2yB0eBS5HBewcw2yKmGHrCuCxZDdBlovGzJrwhfo5cAUB0lFDIfAXfDGnNWifD8OmLdfEzsZt97peyIrEhC84xqRQnlK32XjZkXE5huQGhQiPI0EjQ284RkMqiYxwnoHVpXOMg";
width = 4032;
},
{
height = 2048;
"html_attributions" = (
"Hope Lynch"
);
"photo_reference" = "CoQBdwAAAFMi1hIXlNKawhA7RPl9Oah4OS6ZZyNnBRpgkHtT5gCC0brwkl55azVyulgOLsYeBkz7lpDgrpW4_9A2vg6Dtcg1bf3vVYVb1PbvADXJAV8yNwmRu9xvfSaPlgl3ty7WKW2tl8Znv8pnTMtOxfYBiTqLuFpLiEdt03pmqQMtrTKSEhADBNOSal9jDonQAMac7ghIGhTkHYMlxquEKYBuKNlbJxYY2sMmxQ";
width = 1536;
},
{
height = 3024;
"html_attributions" = (
"\Uc784\Uc77c\Uc8fc"
);
"photo_reference" = "CoQBdwAAAClp7S-w50auLq1Rtet0Glz5UjwWmSFGWKsceURE2ydHve0hFYZqf-OewYNm7xqRBA_Vdtl-nNSIgHawN5JCfyXW48fMRFi7L1mYiycxPjpZSwcH8VlQUisS1dEURkbSaY7lBH1niz197x0hhK0eTIdaPjsXboXcij7xQm6bsYSYEhDt416My2DDwuNUg7MWDrzDGhTIxwfK1eBLCjzto2X_10Ed9pvsyQ";
width = 4032;
},
{
height = 5312;
"html_attributions" = (
"Tim Lee"
);
"photo_reference" = "CoQBdwAAANNU12JQOxIa6Y4MBHzNedo42kZmStvSbw_JF-lhdCOtj7QoiuwfWvj1MjECq29AO7CM3QFeJiQQn3cV3GWilWHoI0EDXBodlGRe3MAG6tNhBnKBYB_jNuM_muu2o1ngWmsOXP6cmcuZmxK1z5w5cDX_aUrpli4vkKRkNuqIdbc_EhACCVmjsS6GxgLanF9s9KrVGhSEL_DpaNArYwocJzkX688WFLsEUQ";
width = 2988;
},
{
height = 3024;
"html_attributions" = (
"Kathleen S"
);
"photo_reference" = "CoQBdwAAAK8OjkKwRH84A_OKMhCXVemX8vxLS8nCp7c30JOvt7SiqGL5_XQCKz03ZiH-Tq2sshn_UBKttz3oyDJIhfAT2VTuDZgnbAPCSlNQUoP80yeATWPJJFcjJ4XxsKcQHF6Y5IDFzszEIAJYhMBQJ9I6RKMaBGMlRftIZeAEkFhN5AEtEhAozH6UEf-m0XthHPES1ldPGhTB3-JgPzRJ8aDX-B5_SyW2vs4E8Q";
width = 4032;
},
{
height = 3024;
"html_attributions" = (
"Deby Lepage"
);
"photo_reference" = "CoQBdwAAAJyut1B1yUQD6mq1FD8gQVNKo16sS6-xbnGeSs8jDtb3C5oF_oUcoUGpLTnQpHqxHfsFh7oL7cBud_h-h0xc2fhNuIkMBFQEWeZhCrmoqph5U79sH98jtOKJgjxs6i0W3-cyDlyURIux8oBfB3QzNhLqeHapJ_WFAMai74Z5ufo1EhDlCT1tkYirOAlgg18i1MVEGhQ_StyBaN3neLaiKNN2s-cTFEPz1w";
width = 4032;
},
{
height = 3024;
"html_attributions" = (
"Deby Lepage"
);
"photo_reference" = "CoQBdwAAAJ-OEm5p7FZZFsPIUBBlB-v5uPhGz3K_j9qD4fIF7lUTFUW3I_-O9gy_MZCUkD5XlZJXa2F9kfZ4Ru-Eb989IYc6YQzc3i_N3ozUOyuPhL2FDUqqkl-pltfNJJBoSOlDp4M4Ay9yrKQP6BpUP8i9P9L0gDgv-ycKDIWNh-vUDmtwEhA6F3RmxZ_tsbE131S_RcYoGhTOQTkUt1Zm9b8qUD7yxiWTjemxxQ";
width = 4032;
},
{
height = 3024;
"html_attributions" = (
"Kathleen S"
);
"photo_reference" = "CoQBdwAAANkAGV7dv_jVNv_mGmJ9ilcPKJ9Vx24Fs1MEwy0Ce6B6hoGZ-8I0pbFVjS99TicGo3zGdi6eUbpEm76C5XplnnkuM4HGWLN1PkzHk98vVeY4hJRGY1o2qnoLaf6DnvPBmhpbrucCJK9WCNRH3-q1UZ6lzFwgxEwFAxbf-KSwJRqkEhD2Si7TWKZNQcb7bXy29QaVGhR7Yk3dOMasHvsoNwa9y-FMxzNV4w";
width = 4032;
},
{
height = 3024;
"html_attributions" = (
"Deby Lepage"
);
"photo_reference" = "CoQBdwAAABqKoM9Is_KWHUlzFyDIAOh41GwUaOqPC5EwWqB_uwDTRsB4XbOksl4qylHlSbTuXpRrUUaAETi-I0coY8KyLtS5E6NxcM4f93iMl6kgsb8apJRGziedKV99EUNcdeaTWmWJOuxirP_7wwiadwUiwbmfjZ05e2EkAtfmjCb8vHTYEhDsAfUeyhcyQu_riR-Vrd9JGhRwlTegpWWdYn9uVGVhs02SjIyXsQ";
width = 4032;
}
);
"place_id" = "ChIJheCrEY6AhYARxCkT8_KjDWE";
rating = "4.4";
reference = "CmRRAAAAeYm_xV5gsn_eVlrvpkEolaqaHFO0CWS5rWXJ5z5QWX8ReJKLPl6eDnvFM0PD2BNMkgfui9Z42_jmUxCIeTeZi3OEaod73XuU_rzLpRAdlOm8IcTaLX6YeYJeS4qFqZxLEhBUzZmWo-SU9WY4YG8WP8GOGhSwAPbhHWRuZh0X6wC1LMD3Los44A";
reviews = (
{
aspects = (
{
rating = 2;
type = overall;
}
);
"author_name" = "Lanxin Chu";
"author_url" = "https://www.google.com/maps/contrib/117750042826931398790/reviews";
language = en;
rating = 4;
"relative_time_description" = "5 months ago";
text = "Red bean shaved ice was good and definitely did not skimp out on ingredients! Green tea latte was solid. Ambiance was pretty nice. There were a lot of people studying there; as noted by others this makes for somewhat limited seating sometimes so keep that in mind.";
time = 1470610849;
},
{
aspects = (
{
rating = 3;
type = overall;
}
);
"author_name" = "Esther Gibbs";
"author_url" = "https://www.google.com/maps/contrib/110692487628239988503/reviews";
language = en;
rating = 5;
"relative_time_description" = "a month ago";
text = "Delicious food and drink- especially their sweet potato latte! Fairtrade and organic everything and a lovely working environment";
time = 1479462640;
},
{
aspects = (
{
rating = 2;
type = overall;
}
);
"author_name" = "Johnny Wang";
"author_url" = "https://www.google.com/maps/contrib/103379264202553362035/reviews";
language = en;
"profile_photo_url" = "//lh6.googleusercontent.com/-EtpIyKVUteI/AAAAAAAAAAI/AAAAAAAAA4c/riPrz4_6j-s/photo.jpg";
rating = 4;
"relative_time_description" = "7 months ago";
text = "It's been called to my attention that I never reviewed this place, despite the number of times I've visited, which is... surprising. Honestly though, there's not too much to say: I've only ever come here for the patbingsoo, which is massively generous in portion size, and fantastically delicious in flavor, and definitely ideal for sharing. But hey, everything can be a personal serving if you try hard enough.\n\nAs for the place itself, it's a nice, chill little cafe that's been packed every single time I go, so seating can be a little hard to find at times. You'll usually find it occupied by folks busy working away on their laptops.\n\n***Accessibility Info***\n\nVenue - On the smaller side, as far as cafes/coffee shops go, with about 2/3 of the seating being accessible: those along the walls were bench seating, and there's lower coffee table seating towards the right as well, leaving only the middle aisle and outer seats along the sides accessible.\n\nBathroom - Didn't try them.";
time = 1465162538;
},
{
aspects = (
{
rating = 2;
type = overall;
}
);
"author_name" = "Victor Vu";
"author_url" = "https://www.google.com/maps/contrib/108347888656400683025/reviews";
language = en;
"profile_photo_url" = "//lh4.googleusercontent.com/-92ZhOOjfwfE/AAAAAAAAAAI/AAAAAAAAZqA/16j_bEwt6fk/photo.jpg";
rating = 4;
"relative_time_description" = "7 months ago";
text = "Great place to study... when it's quiet. There's enough light to clearly see your paperwork. Music is on the medium side and easy to phase out when you put on headphones, or focus really hard. It's really chill!\n\nFood and drinks are nice. It's a great place for coffee and deserts. Most people get waffles or ice cream here. Their matcha green tea is nice as well.\n\nThe only problem is that there is never enough seating during peak hours and it gets claustrophobic when it's crowded with people doing their homework.\n\nSeats are also cheap and hurt your butt.\n\nThis place usually attracts the Asian crowd.";
time = 1463551785;
},
{
aspects = (
{
rating = 1;
type = overall;
}
);
"author_name" = "Brian Melton";
"author_url" = "https://www.google.com/maps/contrib/103909645378067844462/reviews";
language = en;
"profile_photo_url" = "//lh4.googleusercontent.com/-enGmeXKqYC0/AAAAAAAAAAI/AAAAAAAA4eo/maQQGZ8Etdo/photo.jpg";
rating = 3;
"relative_time_description" = "a month ago";
text = "Expensive, small-sized coffees make this coffee shop feel like poor value-for-money. Limited food options but has great desserts: try the macaroons.";
time = 1480554027;
}
);
scope = GOOGLE;
types = (
cafe,
restaurant,
food,
store,
"point_of_interest",
establishment
);
url = "https://maps.google.com/?cid=6993426060231780804";
"utc_offset" = "-480";
vicinity = "611 Post Street, San Francisco";
website = "http://www.joysplacecafe.com/";
}, "status": OK]
And here is my code with a dummy query:
let url = URL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJheCrEY6AhYARxCkT8_KjDWE&key=[MYAPIKEY]")
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) {
(data, response, error) in
guard error == nil else {
print(error!)
return
}
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
guard let placeData = try JSONSerialization.jsonObject(with: responseData, options: JSONSerialization.ReadingOptions.allowFragments)
as? [String: Any] else {
print("error trying to convert data to JSON")
return
}
print("The placeData is: \(placeData.description)")
guard let website = placeData["website"] as? String else {
print("Could not get the website from JSON")
return
}
print("The title is: \(website)")
} catch {
print("error trying to convert data to JSON")
return
}
}
task.resume()
Any help understanding what's going on would be much appreciated. The final objective is to get the Opening hours a Dictionary with the keys being the days of the week and the values being the opening times.
Thanks in advance
The problem is that reponseData is a dictionary with a key response containing the actual dictionary you want. The JSON looks something like:
{
"result": {
"website": "example.com"
}
}
So the correct code would be:
let url = URL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJheCrEY6AhYARxCkT8_KjDWE&key=[MYAPIKEY]")
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) {
(data, response, error) in
guard error == nil else {
print(error!)
return
}
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
guard let placeData = try JSONSerialization.jsonObject(with: responseData, options: JSONSerialization.ReadingOptions.allowFragments)
as? [String: Any] else {
print("error trying to convert data to JSON")
return
}
print("The placeData is: \(placeData.description)")
guard let website = (placeData["result"] as? [String : Any])?["website"] as? String else {
print("Could not get the website from JSON")
return
}
print("The title is: \(website)")
} catch {
print("error trying to convert data to JSON")
return
}
}
task.resume()
I simply changed:
guard let website = placeData["website"] as? String else {
to:
guard let website = (placeData["result"] as? [String : Any])?["website"] as? String else {

Resources