When trying to assign a long JSON response to a Dictionary, I get either
nil
or
Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Assigning a short response works fine. Here is my code
func getUserInfo() {
let access_token : String = accessToken_json_response["access_token"] ?? "empty"
if access_token != "empty" {
Alamofire.request("https://api.github.com/user?access_token=\(access_token)").responseJSON { response in
if let json = response.result.value {
print(json) //The JSON prints, but takes more than a second to do so.
self.getUser_json_response = json as? Dictionary<String, String> //This produces the thread error when the response is long.
print(self.getUser_json_response) //This either prints nil, or a thread error produces in the previous instruction
}
}
}
}
First of all you are casting to an optional dictionary so it should be conditional binding i.e:
if let unwrappedJson = json as? ....
Second, you should cast to [String : Any] i.e:
if let unwrappedJson = json as? [String : Any]
You have to serialise the response into json and then you can use it as dictionary.
eg: let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
then print this json
Or
Use this link, this is latest update from apple to code and encode json response according to your class or model.
Automatic JSON serialization and deserialization of objects in Swift
may this help..
Alamofire.request(UrlStr, method: .post, parameters: params, encoding: URLEncoding.default, headers: nil)
.validate()
.responseJSON { response in
switch response.result {
case .success:
if let JSON = response.result.value {
print("JSON: \(JSON)")
let jsonResponse = (JSON as? [String:Any]) ?? [String:Any]()
print("jsonResponse: \(jsonResponse)")
}
case .failure(let error):
print(error.localizedDescription)
}
}
Related
I got data from API in this format but the problem is that I want to get all questions and answers from the API but whenever I try to get the value by using the key value it returns nil value and application crashes
this is my api data looks like after getting into a dictionary
here's my code for getting data from API
Alamofire.request(url, method: .post, parameters: parameters,encoding: JSONEncoding.default, headers: header ).responseJSON {
response in
switch response.result {
case .success:
print(response)
if let result = response.result.value {
print(result)
let responseDict = result as! [String : Any]
print(responseDict)
let data = responseDict["Result"] as! [Any]
print(data)
}
break
case .failure(let error):
print(error)
}
}
You can try
if let res = responseDict["Result"] as? [[String:Any]] {
for item in res {
if let ques = item["Question"] as? String {
print(ques)
}
if let op = item["Options"] as? [[String:Any]] {
print(op)
}
}
}
I'm working with a non-profit organisation to help them develop a mobile application for their website (so they provided me with the backend services, etc)
Their login PHP service accepts data in JSON, and returns a true or false value in the form of JSON data, but I'm having trouble processing the response in Swift. I'm using Alamofire to connect to the HTTP service.
I'm attaching my code and the exception message I'm receiving below, would really appreciate some help
func authenticateUser (un: String, pw: String) -> Bool
{
var checker = false
let jsonDict : [String: String] = ["volunteer_email": un, "volunteer_pass": pw]
Alamofire.request("www.sampleurl.com/login.php", method: .post, parameters: jsonDict, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if response.result.value != nil{
print (response.result.value)
let resp = response.result.value as! NSDictionary
let results = resp["status"] as! [[String:Any]]
//Change the boolean value of checker based on the value of the results constant
print (results)
}
break
case .failure(_):
print(response.result.error)
break
}
}
return checker;
}
Log:
Optional(<__NSSingleObjectArrayI 0x600000009b50>( {
status = false; } ) ) Could not cast value of type '__NSSingleObjectArrayI' (0x10e28c528) to 'NSDictionary'
(0x10e28d1a8). 2018-05-09 12:13:00.177091+0530 TestApp1 [16680:817883]
Could not cast value of type '__NSSingleObjectArrayI' (0x10e28c528) to
'NSDictionary' (0x10e28d1a8). (lldb)
Log for response.result.value:
Note: "status":"false"/"true" is the output from the web service
Optional(<__NSSingleObjectArrayI 0x60400001b160>(
{
status = false;
}
))
Note: I did some research and I understood what the NSSingleObjectArray is and what causes it, but I'm stuck here as the service passes back only a single JSON value to my app. Is there any way to handle this without requesting the organisation to change their code? Logically, shouldn't I be able to cast the response into an NSDictionary regardless of its size?
Also, the reason why I've specified that the returned data can be of type any, is because I ran into an issue that can be found here:
Other StackOverflow question
Thanks so much in advance :)
Since you're using .responseJSON of Alamofire, you should make use of Alamofire's parameterized enums. It provides the json object in .success. So doing case .success(_) is wasteful.
Go ahead with this and no need of typecasting response.result.value at all.
Alamofire
.request("www.sampleurl.com/login.php",
method: .post,
parameters: jsonDict,
encoding: JSONEncoding.default,
headers: nil)
.responseJSON { (response) in
switch(response.result) {
case .success(let responseJSON):
print(responseJSON)
/*
As an improvement:
To obtain an easy-access object, convert responseJSON to either a:
1. Codable model:
let model = JSONDecoder().decode(SomeModel.self,
from: responseJSONData)
2. SwiftyJSON object: (available on GitHub)
let json = JSON(responseJSON)
Doing so will basically make accessing the inner elements easier.
*/...
case .failure(let error):
print(error)
}
}
BTW, just FYI: the response is an array of dictionaries, not a dictionary of array of dictionaries.
Use NSArray instead of NSDictionary
func authenticateUser (un: String, pw: String) -> Bool{
var checker = false
let jsonDict : [String: String] = ["volunteer_email": un, "volunteer_pass": pw]
Alamofire.request("www.sampleurl.com/login.php", method: .post, parameters: jsonDict, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if response.result.value != nil{
print (response.result.value)
let resp = response.result.value as! NSArray
let results = resp["status"] as! [[String:Any]]
//Change the boolean value of checker based on the value of the results constant
print (results)
}
break
case .failure(_):
print(response.result.error)
break
}
}
return checker;
}
let url = "(InsertAsset)?customerID=(vmanagerappDelegate.cust_Id!)&assetTag=(self.txt_AssetTag.text! as String)&modelID=(modelObject)&statusID=(statusObject)&serial=(self.txt_Serial.text! as String)&assetName=(self.txt_AssetName.text! as String)&purchaseDate=(selectedPurchaseDate)&supplierID=(supplierObject)&purchaseCost=(purchaseCostObject)&warranty=(self.txt_Warranty.text! as String)¬es=(notesObject)&locationID=(locationObject)&ownerID=(ownerObject)&addUserID=(vmanagerappDelegate.userId as String)&saleEndDate=(self.txt_Sale_End_Date.text! as String)&softwareMaintainenceEndDate=(self.txt_Software_Maintainence_End_Date.text! as String)&supportEndDate=(self.txt_Support_End_Date.text! as String)&MacAddress=(self.txt_Mac_Address.text! as String)&sitekey=testing"
Hi you can create dictionary like following to send parameter as dictionary in Alamofire :
var dicParam = Dictionary<String,AnyObject>()
dicParam[“customerID”] = vmanagerappDelegate.cust_Id!
dicParam[“assetTag”] = self.txt_AssetTag.text! as String
dicParam["modelID"] = modelObject
In Alamofire pass above dictionary as parameters along with your URL like following :
Alamofire.request("Your URL", method: .post, parameters: dicParam, encoding: URLEncoding(destination: .queryString), headers: nil).responseJSON {
response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
try creating a dicitonary
let params:Dictionary<String, AnyObject> = ["customerID":vmanagerappDelegate.cust_Id!,"assetTag":self.txt_AssetTag.text,"modelID":modelObject] //similarly add all params to Dict
if you want to add some headers create dicitonary Header for them too and pass in Alamofire.request(.POST,url,parameters: params,headers:Header,encoding: .JSON)
a example for post request
func remotePOSTServiceWithParameters(urlString : String , params : Dictionary<String, AnyObject> , callback:(data: Dictionary<String, AnyObject>?, error: NSError? ) -> Void) {
print("Request POST URL:\(urlString) PARAMS:\(params)")
Alamofire.request(.POST,urlString,parameters: params,encoding: .JSON)
.validate()
.responseJSON {
response in
guard response.result.error == nil else {
print("Error for POST :\(urlString):\(response.result.error!)")
//
callback(data: nil , error: response.result.error! )
return
}
if let value = response.result.value {
print("JSON: \(value)")
if let result = value as? Dictionary<String, AnyObject> {
print("Response for POST :\(urlString):\(value)")
callback(data:result , error: nil )
}
}
}
}
I'm calling my webservice with alamofire and trying to parse the json result.
My code looks like this:
Alamofire.request("\(serverURL)/users/\(username)/hashtags")
.validate()
.responseJSON { response in
switch response.result {
case .success:
DispatchQueue.main.async(execute: {
print(response.result.value!)
if let jsonData = response.result.value as? [[String: AnyObject]] {
print("this is not printed")
The first print returns:
{
hashtags = (
test,
elo
);
}
and the 2nd one is not printed at all - the code is never executed. Why?
When I call my webservice in the browser I'm getting:
{"hashtags":["test","test2"]}
The JSON structure you are trying to convert is a dictionary not an array. You are trying to convert the response to an array of dictionary and that's why it is failing.
You need to use:
if let jsonData = response.result.value as? [String: AnyObject]
{
// Handle data
}
i am new in iOS developer . and i just want to ask that when i attached third party library Alamofire using get method the data is coming but not in proper Json form,the key value comes null of each identity..please
help me here is my code:
let headers = ["Authorization":"","Accept": "application/json"]
Alamofire.request(.GET,requestString,headers:headers,encoding: .JSON)
.responseJSON { response in
print(response)
print(response.request)
Try this.
Alamofire.request(.GET, url, parameters: parameter as? [String : AnyObject]).responseJSON { (response: Response<AnyObject, NSError>) in
if error == nil {
print(response.result.value)
}
}
When you call responseJSON, it parses the JSON for you. So, if the JSON was an array of dictionaries (as shown by one of your other questions), then the response.result.value would not contain that raw JSON, but rather a nested structure of arrays and dictionaries. You can retrieve this data by unwrapping it (e.g. with if let or guard let):
Alamofire.request(requestString, headers: headers)
.responseJSON { response in
guard let dictionaries = response.result.value as? [[String: AnyObject]] else {
print(response.result.error)
return
}
// do something with the array of dictionaries, e.g. to show the names
for dictionary in dictionaries {
if let name = dictionary["name"] as? String {
print(name)
} else {
print("Name not found")
}
}
}