Swift 3 Rest API not working - json

Having trouble with Rest API in Swift 3. Here's my code:
func getData()
{
let urlString = "http://dataservice.accuweather.com/locations/v1/regions?apikey=QVU3TATgJEdRyojFze6zivdrmiln9XlA"
let config = URLSessionConfiguration.default // Session Configuration
let session = URLSession(configuration: config) // Load configuration into Session
let url = URL(string: urlString)!
let task = session.dataTask(with: url, completionHandler: {
(data, response, error) in
if error != nil {
print(error!.localizedDescription)
} else {
do {
print("in do block")
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
{
print("if condition is true")
//Implement your logic
print(json)
} else
{
print("Error in json serial")
}
} catch {
print("error in JSONSerialization")
}
}
})
task.resume()
}
After execution I can see the following print statements:
in do block
Error in son serial
Cannot figure out what is wrong with JSON Serialization command here. Expected responses is a JSON array. Any help would be appreciated. Thx

Change the
if let json = try JSONSerialization.jsonObject(with: data!, options:[]) as? [String: Any]
To
if let json = try JSONSerialization.jsonObject(with: data!, options:[]) as? [Any]
beacuse the json you have is "jsonWithArrayRoot" check this for further details.
https://developer.apple.com/swift/blog/?id=37

Related

How to extract value from JSON object with dictionary [Swift 4]

I'm trying to make an async API get request to openweathermap.org 's API. The result should be this JSON structure. I'm particularly trying to get the temperature. I was taught to work with it by wrapping the JSON to a dictionary. Thing is I don't know what I can use to specify the object "main" (in the JSON) and get the temperature. Do I have to iterate object by object? This is my code so far (side note: is it worrying that my app uses 50 mb of RAM?)
let url = URL(string: stringURL)
let myQ = DispatchQueue.init(label: "getCityDetails")
myQ.async {
let session = URLSession.shared
let m = session.dataTask(with: url!, completionHandler: {(data, response, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Error with the response, unexpected status code: \(String(describing: response))")
return
}
do {
if let d = data{
let dictionaryObj = try JSONSerialization.jsonObject(with: d, options: []) as! NSDictionary
print(dictionaryObj)
}
}catch{
print(error.localizedDescription)
}
})
m.resume()
The first point is that the default URLSession works in a background thread so you dont need to create a dispatch queue (alos you are not using it correctly). The second point tries to use optional data not to use try/catch. Finally you could try to use Swift 5 together to the protocol Codable to have better code, simple and secure.
let url = URL(string: "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=439d4b804bc8187953eb36d2a8c26a02")!
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Error with the response, unexpected status code: \(String(describing: response))")
return
}
guard let data = data else {
return
}
guard let dictionaryObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return
}
if let main = dictionaryObj["main"] as? [String: Any], let temperature = main["temp"] {
DispatchQueue.main.async {
print("Temperature: \(temperature)")
}
}
}).resume()

I get escape characters from jsonSerialization and cannot decode them in Swift

I have a project in swift where I post a URL and get the result in json.
The json reply from the url contains many greek letters and for example instead of "Γ" I get "\U0393".
How I can translate the escape characters in swift?
My code is the following:
let url = NSURL(string: "https://www.something.that.creates.a.json.array")!
let task = URLSession.shared.dataTask(with: url as URL) { (data, response, error) -> Void in
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers)
print(jsonResult)
} catch {
print("Json Serialization error")
}
}
}
task.resume()
The escape characters where indeed appearing correct as rmaddy wrote.
But I had to cast the result as [[String : Any]] in order to access the Dictionary inside the array correctly.
let url = NSURL(string: "https://www.something.that.creates.a.json.array")!
let task = URLSession.shared.dataTask(with: url as URL) { (data, response, error) -> Void in
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as! [[String : Any]]
print(jsonResult[0]["description"])
} catch {
print("Json Serialization error")
}
}
}
task.resume()

Getting API Data within Swift

I'm trying to get some data from an API at the address https://api.coinmarketcap.com/v1/ticker/bitcoin/?convert=AUD
I've started a new playground within Xcode, and my code is as follows
let urlString = "https://api.coinmarketcap.com/v1/ticker/bitcoin/?convert=AUD"
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error as Any)
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
let id = parsedData["id"] as! [String:Any]
print(id)
} catch let error as NSError {
print(error)
}
}
}.resume()
However the playground is returning no result. I am quite new to Swift, so some of the syntax may be a little off. Can anyone make a suggestion how to obtain the information obtained at the API address?
Thanks!
You need to import PlaygroundSupport and set needsIndefiniteExecution to true.
Also you have some errors in the code as the result is array and you are casting it into a dictionary [String : Any].
Use the following code:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let urlString = "https://api.coinmarketcap.com/v1/ticker/bitcoin/?convert=AUD"
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error!.localizedDescription)
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!) as! [[String : Any]]
for item in parsedData
{
let id = item["id"] as! String
print(id)
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
}.resume()

Wait until JSON call is finished

I have this code in a part of my app:
let myUrl = NSURL(string: "http://aesolutions.ddns.net/data/load_tasks_calendar.php");
let request = NSMutableURLRequest(url: myUrl! as URL);
request.httpMethod = "POST";
let postString = "id_class=\(UserDefaults.standard.string(forKey: "userClass")!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
MenuViewController.tasksCalendarArray.removeAll()
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error1=\(String(describing: error))")
return
}
var _: NSError?
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSArray
if let parseJSON: NSArray = json {
for index in 0...parseJSON.count-1 {
if (parseJSON[index] is NSNull){
MenuViewController.tasksCalendarArray.removeAll()
}else{
let compito = parseJSON[index] as! [String:Any]
let task = tasks.init(taskId: compito["id"] as! String,taskType: compito["type"] as! String,taskSubject: compito["subject"] as! String,taskDate: compito["date"] as! String,taskComment: compito["comment"] as! String)
MenuViewController.tasksCalendarArray.append(task)
}
}
}
}catch{
print("error2=\(error)")
return
}
DispatchQueue.main.async(execute: {
self.performSegue(withIdentifier: "loginToDiary", sender: self)
});
}
task.resume();
I want to perform the segue only when I load all the array. How can I wait until the json is terminated or is done correctly? Because I noticed that sometimes it is correct and other times it performs the segue and so the array is empty and then in the app there are errors.
Can someone help me also adding an alert with a kind of "loading message" to wait that the array is loading?

Response of JSONSerialization.jsonObject is nil with the method POST in swift 3

this is an example for something i want to do but the line if let json = try JSONSerialization.jsonObject(with: data) as? [String: String] is false because the return of JSONSerialization.jsonObject is nil
func parser(lbl: UILabel){
let postString = "xxx=xxx&xxxx=xxxx==&xxxxx=xxxxx&xxxxxx=xxxxxx&xx=xx"
let url = URL(string: "http://xxxxxxxxxx.com/xxxxxx/xxxxx/xxxxxx.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
lbl.text = "error";
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String] {
DispatchQueue.main.async {
let error = Int(json["success"]!)
let message = json["message"]
lbl.text = message
}
}
} catch let parseError {
print("error to parse: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("response`enter code here` : \(responseString!)")
}
}
task.resume()
}
Try this:
var resultFromServer: Any?
resultFromServer = try JSONSerialization.jsonObject(with: data!, options: [])
This should give you resultFromServer as type of Any?, simply check and typecast depending on the basis of the response you are getting, an array or a dictionary.
Like
if let respdict = resultFromServer as? [String : Any] {
//respone in dictionary format
}
else if let respArr = resultFromServer as? [Any]{
//response is array type
}
else if let stringRespt = String(data: data, encoding: .utf8){
//resp is string
}
Just make changes as per your JSON