How to grab data from an API using Swift 4 and Alamofire - ios

I'm trying to get data from an API with no documentation.
My code is
let URL_MAIN = "http://evarsity.srmuniv.ac.in/srmswi/usermanager/youLogin.jsp"
let URL_ATTENDANCE = "http://evarsity.srmuniv.ac.in/srmswi/resource/StudentDetailsResources.jsp?resourceid=7"
let URL_TIMETABLE = "http://evarsity.srmuniv.ac.in/srmswi/resource/StudentDetailsResources.jsp?resourceid=5"
func getData(url: String) {
Alamofire.request(url, method: .get)
.responseData { response in
if response.result.isSuccess {
print("Sucess! Got the data")
guard let data = response.result.value else { return }
print(data)
} else {
print("Error: \(String(describing: response.result.error))")
}
}
I am getting the response as 51406 bytes.
I need to get the actual data in either JSON or some other format. Here is the api link for python
https://github.com/arjunmahishi/srm-erp-api/blob/master/erp.py

Convert your responseData to a dictionary using the function i provided below and then parse the data accordingly.Here, i m getting a JSON response in the form of a dictionary.
let strResponse = "\(responseString.value!)"
let arr = strResponse.components(separatedBy: "\n")
let dict = convertStringToDictionary(str:(arr.last ?? "")!)
self.Message = dict?["message"] as! String
let responseStatus = dict?["status"] as! NSString
public func convertStringToDictionary(str:String) -> [String: Any]? {
if let data = str.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}

Related

Converting Data from http request from JSON Dictionary of Dictionaries into one Array of Dictionaries in Swift

When Running my http request I get returned the data in the following way.
I am requesting as follows
do {
if let file = URL(string: "https://myhttprequest....") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? [String: Any] {
// json is a dictionary
print(object)
} else {
print("JSON is invalid")
}
} else {
print("no file")
}
} catch {
print(error.localizedDescription)
}
The http request shows like this for example
{"created":[{"id":"-LVEAdIk2KwDmxBj25pK","caption":"Cool watch bro ","creationDate":1546442937.5934439,"imageHeight":1000,"imageUrl":"https://firebasestorage.googleapis.com/..."}],"reshared":[{"id":"-LVEAdIk2KwDmxBj25pK","caption":"Cool watch bro ","creationDate":1546442937.5934439,"imageHeight":1000,"imageUrl":"https://firebasestorage.googleapis.com/..."}]}
I want to be able to put the value of object["created"] and object["reshared"] together to have one array of two dictionaries [[caption:"", creationDate:""...],[caption:"", creationDate:""...]]
I have tried by accessing them individually like object["created"] but its not of type dictionary and I cant seem to figure out how to get it to be one.
UPDATE: So I am now doing the following
guard let uid = Auth.auth().currentUser?.uid else { return }
let url = URL(string: "https://us-central1-flashtrend-bdcd3.cloudfunctions.net/getFeed/\(uid)")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let firstData = data else { return }
let jsonStr = String(data: firstData, encoding: .utf8)!
guard let data = jsonStr.data(using: .utf8) else {
return
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return
}
guard let created = json["created"], let reshared = json["reshared"] else {
return
}
let result = [created, reshared]
print(result)
} catch {
print(error.localizedDescription)
}
}
task.resume()
But when i print it looks weird
[<__NSSingleObjectArrayI 0x600002de2290>(
{
caption = "Cool watch bro ";
creationDate = "1546442937.593444";
id = "-LVEAdIk2KwDmxBj25pK";
imageHeight = 1000;
imageUrl = "https://firebasestorage.googleapis.com/v0/b/flashtrend-bdcd3.appspot.com/o/posts%2FE346E4B7-31D8-4E9E-89F2-DA7C426C0537?alt=media&token=4936ce58-64bb-4d5a-b913-c3b87705614f";
imageWidth = 750;
swipes = 0;
userid = U9097gARoXOus96vT1uBHAcNPs03;
views = 1;
}
)
, <__NSArray0 0x600002df40c0>(
)
]
I have changed the http request result to json string, sample code for you as follow, works fine on my xcode:
let jsonStr = "{\"created\":{\"caption\":\"Cool watch bro \",\"creationDate\":\"1546442937.593444\",\"id\":\"-LVEAdIk2KwDmxBj25pK\",\"imageHeight\":1000,\"imageUrl\":\"https://firebasestorage.googleapis.com/v0/b/flashtrend-bdcd3.appspot.com/o/posts/E346E4B7-31D8-4E9E-89F2-DA7C426C0537?alt:media&token:4936ce58-64bb-4d5a-b913-c3b87705614f\",\"imageWidth\":750,\"swipes\":0,\"userid\":\"U9097gARoXOus96vT1uBHAcNPs03\",\"views\":1},\"reshared\":{\"caption \":\"Cool watch bro\",\"creationDate \":\"1546442937.593444\",\"id \":\"-LVEAdIk2KwDmxBj25pK \",\"imageHeight\":1000,\"imageUrl\":\"https://firebasestorage.googleapis.com/v0/b/flashtrend-bdcd3.appspot.com/o/posts/E346E4B7-31D8-4E9E-89F2-DA7C426C0537?alt:media&token:4936ce58-64bb-4d5a-b913-c3b87705614f\",\"imageWidth\":750,\"swipes\":0,\"userid\":\"U9097gARoXOus96vT1uBHAcNPs03\",\"views\":1}}"
guard let data = jsonStr.data(using: .utf8) else {
return
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return
}
guard let created = json["created"], let reshared = json["reshared"] else {
return
}
let result = [created, reshared]
print(result)
} catch {
print(error.localizedDescription)
}

How to parse json in swift (convert json string to string)

I don't find a way to parse a simple json object into a string object in swift. I have a network request which gives me this json response:
"\"asdf\""
When I try to parse this into a string in swift it looks like this:
"\"asdf\""
according this documentation from apple I should only need to do this:
Apple Swift documentation
let jsonValue = responseData as? String
But that does not work for me.
I need just asdf as string value.
Can anyone help me out?
Thanks in advance.
EDIT:
Here is my network request code:
let stringUrl = "https://test.fangkarte.de/v1.3/test"
let url = URL(string: stringUrl)!
let request = URLRequest(url: url)
let session = URLSession(configuration: URLSessionConfiguration.default)
let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in
if let data = data {
let json = String(data: data, encoding: String.Encoding.utf8)
let response = response as! HTTPURLResponse
if 200...299 ~= response.statusCode {
callback(true, response.statusCode, json!)
} else {
callback(false, response.statusCode, json!)
}
}
})
task.resume()
The value of the variable json is "\"testString\"" and not "testString"
You could try something like:
func parseJSON(_ data: Data) -> [String: Any]? {
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let body = json["data"] as? [String: Any] {
return body
}
} catch {
print("Error deserializing JSON: \n\(error)")
return nil
}
return nil
}
To use:
let data = <variable holding JSON>.data(using: .utf8)
let jsonResult = parseJSON(data)
You get a json string so you can try
let jsonstring = "\"asdf\""
let data = jsonstring.data(using: .utf8)
do {
if let str = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as? String {
print(str)
}
}
catch let caught as NSError
{
}

ios - How to wait api response using Alamofire

I want to ask about Semaphore in Alamofire.
I want the app wait for data from the server return success and continue to execute the code after (synchronous type). I use semaphore, but when the api function is called, the app is suspended...
This code is call data from server:
func getAllModels() -> [String] {
var _modelList:[String] = []
let url = BASE_URL + "getAllProductAndModelv2"
let semaphore = DispatchSemaphore(value: 0)
Alamofire.request(url, method:.get, parameters: [:], encoding: JSONEncoding.default).responseJSON { response in
let data = NSData(contentsOf: URL(string: url)!)
do {
if let data = data, let json = try JSONSerialization.jsonObject(with: data as Data) as? [String: Any], let models = json["models"] as? [[String:Any]] {
for model in models {
if let name = model["name"] as? String {
_modelList.append(name)
}
}
}
}catch {
print("error")
}
semaphore.signal()
}
semaphore.wait()
return _modelList
}
And this code is going to get the result:
let api = RestApiManager()
var result:[String] = api.getAllModels()
print(result)
How to relsove this issuse?
Thank you
Use completion
func getAllModels( completion: #escaping ([String] ,Bool) -> Void) {
var modelList:[String] = []
let url = BASE_URL + "getAllProductAndModelv2"
Alamofire.request(url, method:.get, parameters: [:], encoding: JSONEncoding.default).responseJSON { response in
let data = NSData(contentsOf: URL(string: url)!)
do {
if let data = data, let json = try JSONSerialization.jsonObject(with: data as Data) as? [String: Any], let models = json["models"] as? [[String:Any]] {
for model in models {
if let name = model["name"] as? String {
modelList.append(name)
}
}
completion(modelList,true)
}
}catch {
print("error")
completion([],false)
}
}
}
Then call it
self.getAllModels { (data, success) in
if(success)
{
// use data
}
}

How to parse a api for swift 3?

Have been researching on the parsing for quite a bit. With plethora of information avilable for JSON nothing seems to explain how to do in a sensible way to extract information with swift 3.
This is what got so far
func getBookDetails() {
let scriptUrl = "https://www.googleapis.com/books/v1/volumes?q=isbn:9781451648546" .
let myurl = URL(string:scriptUrl)
let request = NSMutableURLRequest(url: myurl!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: myurl! ) { (data, response, error) in
if error != nil{
print("THIS ERROR",error!)
return
} else{
if let mydata = data{
do{
let myJson = try (JSONSerialization.jsonObject(with: mydata, options: JSONSerialization.ReadingOptions.mutableContainers)) as AnyObject
// print("this is the MY JSON",myJson) ---> prints out the json
if let dictonary = myJson["items"] as AnyObject? {
print("the DICTONARY",dictonary) // ----> OUTPUT
if let dictonaryAA = dictonary["accessInfo"] as AnyObject? {
print("the accessInfo",dictonaryAA)
}
}
} catch{
print("this is the in CATCH")
}
} //data
}
}
task.resume()
}
}
OUTPUT :
the DICTONARY (
{
accessInfo = {
accessViewStatus = SAMPLE;
country = US;
=============
RELEVANT DATA as in https://www.googleapis.com/books/v1/volumes?
q=isbn:9781451648546"
==========================
title = "Steve Jobs";
};
}
)
Just need to parse through the json data to get the name, author and title of the book with reference to isbn.
Know there should be a better way to do things that is easily understandable to someone new into the language
You can parse the api in two ways
Using URLSession:
let rawDataStr: NSString = "data={\"mobile\":\"9420....6\",\"password\":\"56147180..1\",\"page_no\":\"1\"}"
self.parsePostAPIWithParam(apiName: "get_posts", paramStr: rawDataStr){ ResDictionary in
// let statusVal = ResDictionary["status"] as? String
self.postsDict = (ResDictionary["posts"] as! NSArray!) as! [Any]
print("\n posts count:",self.postsDict.count)
}
func parsePostAPIWithParam(apiName:NSString, paramStr:NSString,callback: #escaping ((NSDictionary) -> ())) {
var convertedJsonDictResponse:NSDictionary!
let dataStr: NSString = paramStr
let postData = NSMutableData(data: dataStr.data(using: String.Encoding.utf8.rawValue)!)
let request = NSMutableURLRequest(url: NSURL(string: "http://13.12..205.248/get_posts/")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = nil
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error as Any)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse as Any)
do{
if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
convertedJsonDictResponse = convertedJsonIntoDict.object(forKey: apiName) as? NSDictionary
// callback for response
callback(convertedJsonDictResponse)
}
} catch let error as NSError {
print(error)
}
}
Using Alamofire
func AlamofirePOSTRequest() {
let urlString = "http://13.12..205.../get_posts/"
let para = ["data": "{\"mobile\":\"9420....6\",\"password\":\"56147180..1\",\"page_no\":\"1\"}"]
Alamofire.request(urlString, method: .post, parameters: para , headers: nil).responseJSON {
response in
switch response.result {
case .success:
print("response: ",response)
let swiftyJsonVar = JSON(response.result.value!)
if let resData = swiftyJsonVar["posts"].arrayObject {
self.postsDict = resData as! [[String:AnyObject]]
}
print("\n \n alomafire swiftyJsonVar: ",swiftyJsonVar)
break
case .failure(let error):
print(error)
}
}
}
})
dataTask.resume()
}
First of all, all JSON types are value types in Swift 3 so the most unspecified type is Any, not AnyObject.
Second of all, there are only two collection types in the JSON type set, dictionary ([String:Any]) and array ([Any], but in most cases [[String:Any]]). It's never just Any nor AnyObject.
Third of all, the given JSON does not contain a key name.
For convenience let's use a type alias for a JSON dictionary:
typealias JSONDictionary = [String:Any]
The root object is a dictionary, in the dictionary there is an array of dictionaries for key items. And pass no options, .mutableContainers is nonsense in Swift.
guard let myJson = try JSONSerialization.jsonObject(with: mydata) as? JSONDictionary,
let items = myJson["items"] as? [JSONDictionary] else { return }
Iterate through the array and extract the values for title and authors which is an array by the way. Both values are in another dictionary for key volumeInfo.
for item in items {
if let volumeInfo = item["volumeInfo"] as? JSONDictionary {
let title = volumeInfo["title"] as? String
let authors = volumeInfo["authors"] as? [String]
print(title ?? "no title", authors ?? "no authors")
The ISBN information is in an array for key industryIdentifiers
if let industryIdentifiers = volumeInfo["industryIdentifiers"] as? [JSONDictionary] {
for identifier in industryIdentifiers {
let type = identifier["type"] as! String
let isbn = identifier["identifier"] as! String
print(type, isbn)
}
}
}
}
You are doing wrong in this line
if let dictonaryAA = dictonary["accessInfo"] as AnyObject?
because dictonary here is an array not dictionary. It is array of dictionaries. So as to get first object from that array first use dictonary[0], then use accessInfo key from this.
I am attaching the code for your do block
do{
let myJson = try (JSONSerialization.jsonObject(with: mydata, options: JSONSerialization.ReadingOptions.mutableContainers)) as AnyObject
// print("this is the MY JSON",myJson) ---> prints out the json
if let array = myJson["items"] as AnyObject? {
print("the array",array) // ----> OUTPUT
let dict = array.object(at: 0) as AnyObject//Master Json
let accessInf = dict.object(forKey: "accessInfo") //Your access info json
print("the accessInfo",accessInf)
}
}
Hope this helps you.

Parsing JSON with Alamofire Problems

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
}
}

Resources