I am new to iOS and my task is to fetch data from JSON. I have one JSON and from that I am able to get some data but some no. Please help me .
In this I used code :
NetworkManager.post("http://dev.depolitie.be/dev/public/api/cameras/get_cameras_list", parameters: parameters as [String : AnyObject], success: {(result: NSDictionary) -> Void in
print ("Api Success 22 : result is:\n \(result)")
if let error = result.value(forKey: "error") {
print(error)
}else {
let userDict = result.value(forKey: "data") as! NSDictionary
self.cameraArray = userDict["data"] as! NSArray
let introText = userDict["introtext"] as? Int
print("introtext",introText)
//let firstName = employee["firstName"]! as Strin
// let introtext = userDataAsArray["introtext"]! as Int
// print("introText", introtext)
}
self.cameraTableView.reloadData()
}, failure: {(error: NSDictionary?) -> Void in
print ("Api Failure : error is:\n \(String(describing: error))")
})
The inner data I get by initialising it as array but I am not able to get "introtext" field from JSON.
Try this code..😊
NetworkManager.post("http://dev.depolitie.be/dev/public/api/cameras/get_cameras_list", parameters: parameters as [String : AnyObject], success: {(result: NSDictionary) -> Void in
print ("Api Success 22 : result is:\n \(result)")
if let error = result.value(forKey: "error") {
print(error)
}else {
let userDict = result.value(forKey: "data") as! NSDictionary
let dataArray = userDict["data"] as! NSArray
let firstElementOfDataArray = dataArray.object(at: 0) as! NSDictionary
let adminId = firstElementOfDataArray["admin_id"] as! String
let createdAt = firstElementOfDataArray["created_at"] as! String
let description = firstElementOfDataArray["description"] as! String
}
self.cameraTableView.reloadData()
}, failure: {(error: NSDictionary?) -> Void in
print ("Api Failure : error is:\n \(String(describing: error))")
})
As I said in my comment your introtext is inside the root dictionary, also you need to cast to the proper type String in this case
Try with this code
if let error = result.value(forKey: "error") {
print(error)
}else {
if let userDict = result["data"] as? [String:AnyObject]{
if let cameraArrayValues = userDict["data"] as? [[String:AnyObject]]{
self.cameraArray = cameraArrayValues
}
}
if let introText = result["introtext"] as? String{
print("Introtext:" + introText)
}
}
Related
I am trying to get data out of an array of nested dictionaries which is the result of a JSON response.
func fetchData() {
let urlString = "https://global.api.pvp.net/api/lol/static-data/na/v1.2/champion?api_key=\(self.apiKey)"
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error ?? "ERROR!")
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
print(parsedData)
print(parsedData["type"] ?? "")
print(parsedData["version"] ?? "")
print(type(of: parsedData))
print(type(of: parsedData["data"]!))
//ERROR HERE.
//"Cannot subscript a value of type '[String, Any]' with an index of type '(String, (String, Any).Type)'
let innerItem = parsedData["Aatrox", (String, Any)]
} catch let error as NSError {
print(error)
}
}
}.resume()
Here is what is printed:
["type": champion, "version": 7.4.3, "data": {
Aatrox = {
id = 266;
key = Aatrox;
name = Aatrox;
title = "the Darkin Blade";
};
Ahri = {
id = 103;
key = Ahri;
name = Ahri;
title = "the Nine-Tailed Fox";
};
Akali = {
id = 84;
key = Akali;
name = Akali;
title = "the Fist of Shadow";
};
Alistar = {
id = 12;
key = Alistar;
name = Alistar;
title = "the Minotaur";
};
}]
champion
7.4.3
Dictionary<String, Any>
__NSDictionaryI
I am trying to get the "id" for "Aatrox".
How would i go about doing this?
is it because the type of parsedData["data"]! is __NSDictionaryI??
Thanks for the help.
First you need to extract data Dictionary then access other dictionary.
do {
let parsedData = try JSONSerialization.jsonObject(with: data!, options: []) as! [String:Any]
if let passDic = parsedData["data"] as? [String:Any],
let innerItem = passDic["Aatrox"] as? [String: Any] {
print(innerItem)
}
} catch {
print(error)
}
Seems like it should be let innerItem: [String: Any] = parsedData["Aatrox"]
let data : [string:Any] = parsedData.value(key: "data")
let aatrox : [string:Any] = data["Aatrox"]
print("**id**\(aatrox["id"])")
this thing work for me..
I am new to swift and in programming, and I am trying to parse a JSON with the help of Alamofire and SwiftyJSON, if the JSON file is simple, I have no problems and working good, but when I have something like Dictionary -> Dictionary -> Array -> Dictionary, problems begin, so I have the following code:
func performCYesterdayWeatherFetch(forSelectedCity: String)
{
let properString = forSelectedCity.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
Alamofire.request("http://api.apixu.com/v1/history.json?key=MY_KEY&q=\(properString!)&dt=2016-10-20").responseJSON { (response) -> Void in
guard response.result.isSuccess else
{
print("Error while fetching remote rooms: \(response.result.error)")
return
}
guard let json = response.result.value as? JSON,
let forecastJson = json["forecast"].dictionary else
{
print("YESTERDAY PROBLEM")
return
}
for item in (forecastJson["forecastday"]?.arrayValue)!
{
let day = item["day"].dictionaryObject
guard let yesterdayTempCels = day?["avgtemp_c"] as! Double?,
let yesterdayTempFahr = day?["avgtemp_f"] as! Double? else
{
return
}
MY_KEY - is really my key, the problem is not in that i didn't input the key.
It always get in else here:
guard let json = response.result.value as? JSON,
let forecastJson = json["forecast"].dictionary else
{
print("YESTERDAY PROBLEM")
return
}
They result JSON looks like that:
The thin I need is avgtemp_c and avgtemp_f
What am I doing wrong?
Here you have a solution where you don't even need SwiftyJSON to get those values.
let properString = forSelectedCity.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
Alamofire.request("http://api.apixu.com/v1/history.json?key=MY_KEY&q=\(properString!)&dt=2016-10-20").responseJSON { (response) -> Void
guard let json = response.result.value as? [String: Any],
let forecastDictionary = json["forecast"] as? [String: Any],
let forecastDayArray = forecastDictionary["forecastday"] as? [[String: Any]] else {
print("YESTERDAY PROBLEM")
return
}
for item in forecastDayArray {
guard let day = item["day"] as? [String: Any],
let yesterdayTempCels = day["avgtemp_c"] as? Double,
let yesterdayTempFahr = day["avgtemp_f"] as? Double else {
return
}
// Here you should have the values that you need
}
}
I am using a graph request to get a json using this code:
nextrequest.start({ (response: HTTPURLResponse?, result: Any?) in
print(result)
})
this is the json result below and I have no idea how to access the the data inside such as gender, id and name...
Optional(FacebookCore.GraphRequestResult<FacebookCore.GraphRequest>.success(FacebookCore.GraphResponse(rawResponse: Optional({
gender = male;
id = 1128614937219535;
name = "Rayan Slim";
picture = {
data = {
height = 320;
"is_silhouette" = 0;
url = "https://scontent.xx.fbcdn.net/v/t1.0-1/p320x320/12541113_961418627272501_5451131278168499090_n.jpg?oh=47433bc236ce63ce1c07b92499087f29&oe=586A406A";
width = 320;
};
};
}))))
any help would be greatly appreciated!!!!
After permission has been granted here's the function that works.
if AccessToken.current != nil {
GraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start({ (urlResponse, requestResult) in
switch requestResult {
case .Success(let response):
if let responseDictionary = response.dictionaryValue {
let email = responseDictionary["email"] as? String
print(email)
let first = responseDictionary["name"] as? String
print(first)
if let picture = responseDictionary["picture"] as? NSDictionary {
if let data = picture["data"] as? NSDictionary{
if let profilePicture = data["url"] as? String {
print(profilePicture)
}
}
}
}
case .Failed(let error):
print(error)
}
})
}
This is tested and working in Swift 3, using the Facebook SDK for Swift
let pictureRequest = GraphRequest(graphPath: "me/picture?type=large&redirect=false", parameters: [:])
pictureRequest.start{
(urlResponse, requestResult) in
switch requestResult {
case .failed(let error):
print("error in graph request:", error)
break
case .success(let graphResponse):
if let responseDictionary = graphResponse.dictionaryValue {
print(responseDictionary)
var dict: NSDictionary!
dict = responseDictionary["data"] as! NSDictionary
print(dict)
print(dict["url"])
}
}
}
if let userDataDict = result as? NSDictionary {
self.first_name = userDataDict["first_name"] as? String
self.id = userDataDict["id"] as? String
self.last_name = userDataDict["last_name"] as? String
let pictDict = userDataDict["picture"] as? NSDictionary
let pictureUrl = pictDict?["data"] as? NSDictionary
self.pictureUrl = pictureUrl?["url"] as? String
}
do like
nextrequest.start({ (response: HTTPURLResponse?, result: Any?) in
print(result)
if let userData = result as? [NSObject: Any]
{
if let name = userData["name"] as? String
{
print(name)
}
if let picture = userData["picture"] as? [NSObject: Any] {
if let data = picture["data"] as? [NSObject: Any] {
if let profilePictureURL = data["url"] as? String {
// Now add the data to the UI elements
print (profilePictureURL)
}
}
}
}
})
Make use of some JSON parser, maybe Unbox that makes it easier to handle JSON. This code is not tested, but it is an outline of how you could do it. It is always code to store data in a struct instead of using dictionaries.
typealias JSON = [String: Any]
protocol Model {
init?(json: JSON)
}
func getDataFromFacebook() {
...
nextrequest.start {
(response: HTTPURLResponse?, result: Any?) in
self.handleFacebookResult(result)
}
}
func handleFacebookResult(_ result: Any?) {
guard
let json = result as? JSON,
let person = Person(json: json)
else { return }
//do something with person! :)
}
struct Person: Model {
let name: String
let gender: String
let picture: Picture
init?(json: JSON) {
guard
let name = json["name"] as? String,
let gender = json["gender"] as? String,
let pictureJson = json["picture.data"] as? JSON, // "picture.data" possible when using 'Unbox'
let picture = Picture(json: pictureJson)
else { return nil }
self.name = name
self.gender = gender
self.picture = picture
}
}
struct Picture: Model {
let height: Int // Or maybe float...?
let width: Int // Or maybe float...?
let url: String
init?(json: JSON) {
guard
let height = json["height"] as? Int,
let width = json["width"] as? Int,
let url = json["url"] as? String
else { return nil }
self.height = height
self.width = width
self.url
}
}
Optional({"session":{"_id":"574fe96fa28f9aaadb000034","application_id":41262,"created_at":"2016-06-02T08:08:15Z","device_id":0,"nonce":21576,"token":"5b04f409c06ecf24ad2d9479a1ef7ef78916f864","ts":1464854895,"updated_at":"2016-06-02T08:08:15Z","user_id":0,"id":7274}})
I need to parse and save token from the above dictionary (in Swift)
My request goes like this :
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let dict = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(dict)")
}
task.resume()
Need to parse dict
JSON parsing/mapping can be a pain and time consuming.
I just happen to have made a tool for it :
Jenerator
Download from here and move to /usr/local/bin/
It is a little command line tool written in Swift to generate a Swift model based on a JSON. If I passed it your JSON it gave me back this :
import Foundation
struct SOSession {
var created_at : String
var _id : String
var id : Int
var device_id : Int
var token : String
var updated_at : String
var nonce : Int
var user_id : Int
var ts : Int
var application_id : Int
init(data:[String:AnyObject]) {
self.created_at = (data["created_at"] as? String) ?? ""
self._id = (data["_id"] as? String) ?? ""
self.id = (data["id"] as? Int) ?? 0
self.device_id = (data["device_id"] as? Int) ?? 0
self.token = (data["token"] as? String) ?? ""
self.updated_at = (data["updated_at"] as? String) ?? ""
self.nonce = (data["nonce"] as? Int) ?? 0
self.user_id = (data["user_id"] as? Int) ?? 0
self.ts = (data["ts"] as? Int) ?? 0
self.application_id = (data["application_id"] as? Int) ?? 0
}
static func fromSource(urlString : String) -> SOSession? {
guard let url = NSURL(string: urlString), data = NSData(contentsOfURL: url) else {
return nil
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)
if let outerDict = json as? [String:AnyObject], let dict = outerDict["session"] as? [String:AnyObject] {
return SOSession(data: dict)
}
} catch {}
return nil
}
}
Getting the Token then becomes as simple as this :
let myToken = SOSession.fromSource("someUrl")?.token
To use Jenerator I saved your JSON in a file on my desktop and ran in terminal :
jenerator "$HOME/Desktop/so-1.json" StackOverflowQuestion1 SO
jenerator "path-to-file-with-json" save-file-name class-prefix
You can now copy the generator code to your project.
In Swift 4:
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let data = responseJSON as? [String: Any] {
if let success = data["success"] as? Int {
if success == 1 {
self.dataArray = data["results"] as! Array
label.text = self.dataArray[row]["id"] as? String
// parse in similar fashion
}
}
}
}
do{
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions())
let arrayJSON = resultJSON as! NSArray
let success:NSInteger = arrayJSON["success"] as! NSInteger
if (success == 1 ) ....
json data is the response from the server, i am trying to convert it to integer but i get the conversation error.
This is a working exmaple (tested on my machine)
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let data = data{
print("data =\(data)")
do{
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
let resultDictionary = resultJSON as? NSDictionary
let success = resultDictionary!["success"]!
let successInteger = success as! Int
print("success = \(success)")
if successInteger == 1 {
print("yes")
}else{
print("no")
}
}catch _{
print("Received not-well-formatted JSON")
}
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
where the response is:
{ "error_message" : "No User", "success" : 0}
Note
you said that your server responnes as:
{ "error_message" = "No User"; success = 0; }
and this is not a valid json, you should correct it to match the json that i gave to you
You're casting resultJSON as an NSArray but then you try to use it as a dictionary by subscripting "success".
If the response is a dictionary, then cast the result as a dictionary:
let result = resultJSON as! NSDictionary
let success = result["success"] as! NSInteger
If the response is an array of dictionaries, then first select one of the items before subscripting.
let arrayJSON = resultJSON as! NSArray
let success = arrayJSON[0]["success"] as! NSInteger
Note: when possible, prefer using Swift's typed arrays an dictionaries rather than Foundation's NSArray and NSDictionary. Also you should avoid force casting with !, it's better to unwrap optionals safely with if let ... = ... as? ... or any other mechanism.
Update
Here's an example:
do {
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions())
var success = 0
if let dictJSON = resultJSON as? [String:AnyObject] {
if let successInteger = dictJSON["success"] as? Int {
success = successInteger
} else {
print("no 'success' key in the dictionary, or 'success' was not compatible with Int")
}
} else {
print("unknown JSON problem")
}
if success == 1 {
// yay!
} else {
// nope
}
In this example I'm using a Swift dictionary [String:AnyObject] instead of an NSDictionary, and I'm using a Swift integer Int instead of Foundation's NSInteger. I'm also typecasting with if let instead of forcing.