Accessing JSON with Swift - ios

I am currently developing an app and I want to display some information about a particular place. I am using Google Places API to do this and am trying to extract some information from this JSON response:
{
"html_attributions": [],
"result": {
"address_components": [],
"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": {},
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id": "4f89212bf76dde31f092cfc14d7506555d85b5c7",
"international_phone_number": "+61 2 9374 4000",
"name": "Google",
"photos": [],
"place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"rating": 4.5,
"reference": "CmRaAAAAVvEJLOszIgZMqrn59xg_wEmLJUpC52Zd7HZzzcv0OsaRobY_f8galxBVNsyEgC9nhUsI7BQQcTYCA0t_f8JlhEV-dftt-OhapkRRvQ12g6R3FU-d6OWB-T1vYVIcRuEBEhBha4swICH7pUUsjBRivnHTGhT1Y97NAmr0iWe4qffGJH0iY96GKg",
"reviews": [],
"scope": "GOOGLE",
"types": [
"point_of_interest",
"establishment"
],
"url": "https://maps.google.com/?cid=10281119596374313554",
"user_ratings_total": 133,
"utc_offset": 660,
"vicinity": "5 48 Pirrama Road, Pyrmont",
"website": "https://www.google.com.au/about/careers/locations/sydney/"
},
"status": "OK"
}
The code I am using in my view controller is:
let reposURL = NSURL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=\(chosenPlaceID!)&key=SOMEAPIKEY")!
if let JSONData = NSData(contentsOfURL: reposURL) {
if let json = (try? NSJSONSerialization.JSONObjectWithData(JSONData, options: [])) as? NSDictionary {
if let reposArray = json["result"] as? [NSDictionary] {
for item in reposArray {
placeRepositories.append(PlaceRepository(json: item ))
}
}
}
}
The code in my placeRepository controller is:
class PlaceRepository {
var name: String?
var formattedAddress: String?
var formattedPhoneNumber: String?
var internationPhoneNumber: String?
var types: [String]?
init(json: NSDictionary) {
self.name = json["name"] as? String
self.formattedAddress = json["formatted_address"] as? String
self.formattedPhoneNumber = json["formatted_phone_number"] as? String
self.internationPhoneNumber = json["international_phone_number"] as? String
self.types = json["types"] as? [String]
}
}
I have put a breakpoint in to try and find out what is going on and the for item in reposArray code is never accessed, it gets skipped over in the previous if statement but I am not sure why? Any help would be greatly appreciated.
Thank you.

Your response suggests json["result"] is not array of dictionary ... [NSDictionary] ... its NSDictionary
change this line
if let reposArray = json["result"] as? [NSDictionary] { ... }
with
if let reposArray = json["result"] as? NSDictionary {
PlaceRepository(json: reposArray )
}
After that you can't loop NSDictionary like
for item in reposArray { .. }

You can use third party libraries like SwiftyJson It's make JSON parsing more easy task.

Related

How to pasre JSON (dictionary and array) using the new Swift 3 and Alamofire

Can any one suggest and send me sample code for fetching JSON response. Few APIs I am getting data in the form of the NSDictionary and few APIs I am getting data in the form of NSArray.
This is my API request with Alamofire.
APIManager.sharedInstance.getTeacherProfileDataFromURL(){(userJson)-> Void in
let swiftyJsonVar = JSON(userJson)
print("userJson userJson userJson userJson",userJson)
print("swiftyJsonVar",swiftyJsonVar)
}
1) API WITH JSON ARRAY OF DATA
{
"status": 1,
“student”: [
{
"name": "Sprouse",
"subject": [
“english”
],
"personal_email": "",
"school_email": "cole.sprouse483#demo.in",
"phone": "9665478544",
"class_teacher": false,
"image": "/assets/default_male.png"
},
{
"name": “elen”,
"subject": [
"Social Science"
],
"personal_email": "",
"school_email": "elena.gilbert564#demo.in",
"phone": "9066260799",
"class_teacher": false,
"image": "/assets/default_female.png"
},
],
"message": "Details fetched successfully."
}
2) ANOTHER API WITH JSON DICTIONARY OF DATA
{
"status": 1,
"dashboard": {
"announcement": [
{
"title": "Independence Day Celebration",
"posted_on": "13 August, 2017"
}
],
"student": {
"attendance_percent": 100,
"assignment": [
{
"title": "Alphabets in HINDI",
"end_date": "13/09/2017",
"subject": "Hindi",
"teacher_name": "Bonnie Bennette"
}
],
"leave_apply": 13
},
"image": "/system/images/86/j1f9DiJi_thumb.jpg?1504593436"
},
"message": "Details fetched successfully."
}
1) API WITH JSON ARRAY OF DATA
let swiftyJsonVar = JSON(userJson)
let array : [[String : String]] = swiftyJsonVar["student"]
This will give you an array of dictionaries or key-values of student.
Further you can get another value from the array like that
let name : String = array[0]["name"]
2) ANOTHER API WITH JSON DICTIONARY OF DATA
let swiftyJsonVar = JSON(userJson)
let dictionary : [[String : String]] = swiftyJsonVar["dashboard"]
This will give you an array of dictionary or key-value of dashboard.
let array : [[String : String]] = dictionary["announcement"]
This will give you the array of announcement and next you can get the further values like this
let name : array = array[0]["title"]
i have resolved my issue long back , posting lately this is my answer it may helpful for other thats why i am posting here.
if data is in the form of array.
DispatchQueue.main.async {
TeacherAPIManager.sharedInstance.FetchTeacherStudentAttendanceDataFromURL(){(attendanceJson)-> Void in
print("observationInfo --",attendanceJson)
let swiftyAttendanceJsonVar = JSON(attendanceJson)
let observation = swiftyAttendanceJsonVar["list"].rawString()!
let jsonData = observation.data(using: .utf8)!
let array = try? JSONSerialization.jsonObject(with: jsonData, options: []) as! Array< Any>
for observationVar in array!{
let totlDic = NSMutableDictionary()
let dic = observationVar as! Dictionary<String,Any>
}
}
if data is in the form of dictionary. just replace this below of line code in above function array line.
let dictionary = try? JSONSerialization.jsonObject(with: jsonData, options: []) as! Dictionary<String, Any>

How to parse Array of JSON to array in Swift

I'm trying to parse JSON which is like below
[
{
"People": [
"Jack",
"Jones",
"Rock",
"Taylor",
"Rob"
]
},
{
"People": [
"Rose",
"John"
]
},
{
"People": [
"Ted"
]
}
]
to an array which results in:
[ ["Jack", "Jones", "Rock", "Taylor", "Rob"] , ["Rose", "John"], ["Ted"] ]
which is array of arrays.
I tried with code below
if let path = Bundle.main.path(forResource: "People", ofType: "json") {
let peoplesArray = try! JSONSerialization.jsonObject(
with: Data(contentsOf: URL(fileURLWithPath: path)),
options: JSONSerialization.ReadingOptions()
) as? [AnyObject]
for people in peoplesArray! {
print(people)
}
}
when I print "people" I get o/p as
{
People = (
"Jack",
"Jones",
"Rock",
"Taylor",
"Rob"
);
}
{
People = (
"Rose",
"John"
);
}
...
I'm confused how to parse when it has "People" repeated 3 times
Trying to display content in UITableView where my 1st cell has "Jack" .."Rob" and Second cell has "Rose" , "John" and third cell as "Ted"
PLease help me to understand how to achieve this
You can do this in an elegant and type safe way leveraging Swift 4 Decodable
First define a type for your people array.
struct People {
let names: [String]
}
Then make it Decodable, so that it can be initialised with a JSON.
extension People: Decodable {
private enum Key: String, CodingKey {
case names = "People"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Key.self)
self.names = try container.decode([String].self, forKey: .names)
}
}
Now you can easily decode your JSON input
guard
let url = Bundle.main.url(forResource: "People", withExtension: "json"),
let data = try? Data(contentsOf: url)
else { /* Insert error handling here */ }
do {
let people = try JSONDecoder().decode([People].self, from: data)
} catch {
// I find it handy to keep track of why the decoding has failed. E.g.:
print(error)
// Insert error handling here
}
Finally to get get your linear array of names you can do
let names = people.flatMap { $0.names }
// => ["Jack", "Jones", "Rock", "Taylor", "Rob", "Rose", "John", "Ted"]
var peoplesArray:[Any] = [
[
"People": [
"Jack",
"Jones",
"Rock",
"Taylor",
"Rob"
]
],
[
"People": [
"Rose",
"John"
]
],
[
"People": [
"Ted"
]
]
]
var finalArray:[Any] = []
for peopleDict in peoplesArray {
if let dict = peopleDict as? [String: Any], let peopleArray = dict["People"] as? [String] {
finalArray.append(peopleArray)
}
}
print(finalArray)
output:
[["Jack", "Jones", "Rock", "Taylor", "Rob"], ["Rose", "John"], ["Ted"]]
In your case, it will be:
if let path = Bundle.main.path(forResource: "People", ofType: "json") {
let peoplesArray = try! JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path)), options: JSONSerialization.ReadingOptions()) as? [Any]
var finalArray:[Any] = []
for peopleDict in peoplesArray {
if let dict = peopleDict as? [String: Any], let peopleArray = dict["People"] as? [String] {
finalArray.append(peopleArray)
}
}
print(finalArray)
}
let assume that the json is the encoded data
var arrayOfData : [String] = []
dispatch_async(dispatch_get_main_queue(),{
for data in json as! [Dictionary<String,AnyObject>]
{
let data1 = data["People"]
arrayOfData.append(data1!)
}
})
You can now use the arrayOfData. :D
what you have here is first an array of 3 objects. each object is a dictionary where the key is people and the value is an array of strings. when you're trying to do jsonserialization, you have to cast it down to the expected result. So you have first an array of objects, then you have a dictionary with String: Any, then you obtain an array of String
let peoplesArray = try! JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path)), options: []) as? [AnyObject]
guard let peoplesObject = peoplesArray["people"] as? [[String:Any]] else { return }
for people in peoplesObject {
print("\(people)")
}
I couldn't pasted it in a comment, it is too long or something
static func photosFromJSONObject(data: Data) -> photosResult {
do {
let jsonObject: Any =
try JSONSerialization.jsonObject(with: data, options: [])
print(jsonObject)
guard let
jsonDictionary = jsonObject as? [NSObject: Any] as NSDictionary?,
let trackObject = jsonDictionary["track"] as? [String: Any],
let album = trackObject["album"] as? [String: Any],
let photosArray = album["image"] as? [[String: Any]]
else {
return .failure(lastFMError.invalidJSONData)
}
}
}
And the json was something like:
{
artist: {
name: Cher,
track: {
title: WhateverTitle,
album: {
title: AlbumWhatever,
image: {
small: "image.px",
medium: "image.2px",
large: "image.3px"}
....

iOS swift separate JSON into array

I have a JSON file like this:
{
"timeline": {
"Milan": {
"placeA": [
{
"name": "Place 1",
"kind": "historic",
},
{
"name": "Place 2",
"kind": "historic",
},
{
"name": "Place 3",
"kind": "historic",
}
]
},
"Paris": {
"placeB": [
{
"name": "Place 1",
"kind": "historic",
},
{
"name": "Place 2",
"kind": "historic",
}
]
}
}
}
and in my app I need to separate this JSON and insert into a array like this for separate data with tableView section:
var arr = [[placeA],[placeB],...]
how can I do that?
P.S I use SwiftyJson
struct City {
let name : String
let kind : String
}
var cities = [City]()
let path = (try? Data(contentsOf: URL(string: "http://www.yourwebsite.json")!)) as Data!
// let jsonData = NSData(contentsOfFile: path) as NSData!
var error : NSError?
let ReadableJSON2 = JSON ( data:path!, options: JSONSerialization.ReadingOptions.mutableContainers, error: nil )
print(error)
do {
let jsonObject = try JSONSerialization.jsonObject(with: path!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
for city in jsonObject["cities"] as! [[String:AnyObject]] {
//let coordinates = position["Position"] as! [String:CLLocationDegrees]
let Cityname = city["name"] as! String
let Citykind = city["kind"] as! String
let city = City(name: cityName,description: description, )
cities.append(city)
}
} catch let error as NSError {
print(error)
}

Swift and JSON parsing only an object not an array

I am working on a weather app that parses JSON data and sets the text of my label to the temp value of the JSON request. I got the value of id from the weather object array, but the temp is not in an array it is just an object. Can someone please tell me where I am wrong. My value is reurning nil because I am not fetching it correctly. Here is my snippet and JSON.
#IBAction func getWeather(sender: AnyObject) {
let requestURL: NSURL = NSURL(string: "http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=MYAPPID")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("JSON Downloaded Sucessfully.")
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let today = json["weather"] as? [[String: AnyObject]] {
//this is pulling 4 key value pairs
for weather in today {
//this works
let id = weather["id"]?.stringValue
self.trumpDescription.text=id;
print(id)
//this is where I am confused it changes from an array to just an object
let temp = json["temp"] as? String
self.currentTempView.text=temp;
print(temp)
}
}
}
catch {
print("Error with Json: \(error)")
}
}
}
task.resume()
}`
Here is the JSON:
{
"coord": {
"lon": 138.93,
"lat": 34.97
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04n"
}
],
"base": "cmc stations",
"main": {
"temp": 292.581,
"pressure": 1019.48,
"humidity": 99,
"temp_min": 292.581,
"temp_max": 292.581,
"sea_level": 1028.92,
"grnd_level": 1019.48
},
"wind": {
"speed": 5.36,
"deg": 237.505
},
"clouds": {
"all": 64
},
"dt": 1464964606,
"sys": {
"message": 0.0037,
"country": "JP",
"sunrise": 1464895855,
"sunset": 1464947666
},
"id": 1851632,
"name": "Shuzenji",
"cod": 200
}
It looks like it should be
if let main = json["main"] as? NSDictionary {
let temp = main["temp"] as! String
print(temp)
}
Instead of this:
let temp = json["temp"] as? String
Try this:
if let main = json["main"] as? [String: AnyObject] {
let temp = main[temp]?.stringValue
print(temp)
//alternatively you can try this as per your convenience of data type
let tempNew = main[temp]?.doubleValue
print(tempNew)
}

Json Tableview Swift

this post follows an old post where some people helped me for a similar problem.
I currently developing an app which list user object by making an request to a webservice, which send a response in JSON in this format :
{
"objects": [
{
"id": "28",
"title": "test",
"price": "56 €",
"description": "kiki",
"addedDate": "11-07-2015",
"user_id": "1",
"user_name": "CANOVAS",
"user_zipCode": "69330",
"category_id": "1",
"category_label": "VEHICULES",
"subcategory_id": "1",
"subcategory_label": "Voitures",
"picture": "",
"bdd": {},
"picture_url": "http://jdl-barreme-orange.dyndns.org/WEBSERVICE/pictures/test.JPG"
},
{
"id": "27",
"title": "ferrari",
"price": "55 €",
"description": "rouge jantes",
"addedDate": "11-07-2015",
"user_id": "1",
"user_name": "CANOVAS",
"user_zipCode": "69330",
"category_id": "1",
"category_label": "VEHICULES",
"subcategory_id": "1",
"subcategory_label": "Voitures",
"picture": "",
"bdd": {},
"picture_url": "http://jdl-barreme-orange.dyndns.org/WEBSERVICE/pictures/ferrari.JPG"
}
}
I search a method to retrieve for each dictionary the value title and price and put them in a tableView.
Code I used (tableviewcontroller) :
if let jsonArray = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: nil) as? [[String:AnyObject]] {
for dict in jsonArray {
if let title = dict["title"] as? String {
println(title)
}
}
}
But it doesn't work, I put a breakpoint, and Xcode stop to interpret here :
for dict in jsonArray
Thanks for your help.
This example JSON is not valid: it lacks a ] before the last }.
But I guess this is just a pasting typo and the JSON you're using is properly formatted, so your problem is that you need to first access the objects key of your dictionary.
This key holds a value of an array of dictionaries, so we're using it as a typecast:
if let json = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: nil) as? [String:AnyObject] {
if let objects = json["objects"] as? [[String:AnyObject]] {
for dict in objects {
if let title = dict["title"] as? String {
println(title)
}
}
}
}
First we cast the result of NSJSONSerialization.JSONObjectWithData as the dictionary: [String:AnyObject], then we access the value for the objects key, then we cast this value as an array of dictionaries: [[String:AnyObject]].
Remember, with JSON format, dictionaries are formatted with {} and arrays are formatted with [].
Your example is {key:[{},{}]} so it's a dictionary holding an array of dictionaries.
Update for Swift 2.0
if let json = try? NSJSONSerialization.JSONObjectWithData(urlData!, options: []) as? [String:AnyObject] {
if let objects = json?["objects"] as? [[String:AnyObject]] {
for dict in objects {
if let title = dict["title"] as? String {
print(title)
}
}
}
}
Try this :
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
var DataFromJSon = jsonResult["objects"] as! NSArray
for one in DataFromJSon {
var title = one["title"] as! String
println(title)
}

Resources