Serializing JSON object with Alamofire - ios

Im trying to run to serialize the JSON response, but I am getting an error on the "let json = ..." line. The error is "Ambiguous reference to member 'jsonObject(with:options:)'". If anyone knows how to fix this I will apprechiate it
Alamofire.request("https://httpbin.org/get").responseJSON { response in
if let JSON = response.result.value {
do {
let json = try JSONSerialization.jsonObject(with: response.result.value!, options: .allowFragments)
} catch {
print ()
}
print("JSON: \(JSON)")
}
}

Because response.result.value is type of a dictionary __NSDictionaryI, not a Data as jsonObject expected. You can retrieve value from JSON with ease, no need to convert to json, for example: JSON["title"]

Related

Assigning a long JSON response to Dictionary produces a Thread error

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

NSJSONSerialization Error : Why am I not able to catch the error in try catch block? swift 3.0

I am calling REST API to get a response from the server and also testing for bad data type to caught in try catch block nut app still crashes with below error:
Could not cast value of type '__NSArrayM' (0x10575ee00) to 'NSDictionary' (0x10575f2d8).
let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error!)
return
}
do {
let responseObject = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String,String>
print(responseObject)
} catch let jsonError {
print(jsonError)
}
}
dataTask.resume()
For this, I also found the solution that I should check data with JSON format first then use JSONSerialization.
if JSONSerialization.isValidJSONObject(data){
responseObject = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String,String>
}
else {
print("Error")
}
I want to know that if type cast value error not caught by the try-catch block then what is a use of try-catch block in network call. I can simply check for the JSON format and the pass the response object.
What is a good programming practice?
NOTE : Error is not an issue I just don't want my should crash an app when data type changes form dictionary to array or other than specified type.
This is not about valid JSON, you are getting this crash because your JSON at root is Array not Dictionary and you are trying to cast the result of jsonObject(with:) to Dictionary that is the reason you are getting this crash also there is no need to specify mutableContainers with Swift.
do {
let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as! [[String:Any]]
print(responseObject)
} catch let jsonError {
print(jsonError)
}
Edit: If you don't know your JSON time then you can use if let like this way.
do {
let responseObject = try JSONSerialization.jsonObject(with: data, options: [])
if let responseArray = responseObject as? [[String:Any]] {
//Access array
}
else if let responseDictionary = responseObject as? [String:Any] {
//Access dictionary
}
print(responseObject)
} catch let jsonError {
print(jsonError)
}

Alamofire can't access keys of json response

I'm new to using Alamofire and have encountered an issue. I'm able to run the following code to print out all the data from an API endpoint.
Alamofire.request("http://codewithchris.com/code/afsample.json").responseJSON { response in
if let JSON = response.result.value {
print(JSON)
}
}
The issue is that when I run this:
Alamofire.request("http://codewithchris.com/code/afsample.json").responseJSON { response in
if let JSON = response.result.value {
print(JSON["firstkey"])
}
}
I get the error:
Type 'Any' has no subscript members
I don't know why this error is happening, it seems as if I'm accessing the data correctly. Any help would be great, thanks!
I have tried formatting it using both:
print(JSON["firstkey"] as String)
and
print(JSON["firstkey"] as [String:Any]
but they still give the same error.
This is the JSON on my endpoint:
{
"firstkey":"it worked!",
"secondkey":["item1", "item2", "item3"]
}
This is really simple. You just need to force cast (as!) your JSON. so change your code to this and it will work:
Alamofire.request("http://codewithchris.com/code/afsample.json").responseJSON { response in
if let JSON = response.result.value {
let json = JSON as! [String: Any]
print(json["firstkey"])
}
}
Edit 1:
As you said in comments that you are using SwiftyJSON package. Sample code is as follows:
Alamofire.request("http://codewithchris.com/code/afsample.json").responseJSON { response in
if let value = response.result.value {
let json = JSON(value)
print(json["firstkey"].stringValue)
}
}
Alamofire.request("https://mmcalc.com/api").responseJSON { response in
if let value = response.result.value {
let json = JSON(value)
print(json.arrayValue[0]["uniqueUsers"].stringValue)
}
}
You are trying to get the value with getting the object, try this:
Alamofire.request("http://codewithchris.com/code/afsample.json").responseJSON { response in
if let result = response.result.value {
let JSON = result as! NSDictionary
print(JSON["firstkey"])
}
}
Hope it will work!
You should add ! at the end of code before ) to force unwrap the value
Alamofire.request("http://codewithchris.com/code/afsample.json").responseJSON { response in
if let JSON = response.result.value {
let json = JSON as! [String: Any]
print(json["firstkey"]!)
}
}

JSON response from server in Swift

I'm calling an api in swift 3. And from the api I'm getting response in JSON String format. How to convert that JSON String to Dictionary or Array in Swift. Also that JSON string contains further array's and dictionaries.
I've tried using EVReflection tool. It's only converting the upper JSON object in dictionary. The nested dictionaries and array's are still in String format.
Try something like this, response is [String: Any] so you must cast to a any type
DispatchQueue.main.async {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
let j = json as NSDictionary
guard let resp = response as? HTTPURLResponse
else {
// No response from server
return
}
if resp.statusCode == 200 {
// You can put here some callback, this is a data you need
} else {
// Here is some error
}
}
} catch {
// And this is a error from server
}
}
You should receive jsonData which you can directly try JSONSerialization.
If for any reason you receive it as json String then you have to convert that string to jsonData first
// Here you have to convert Json String to jsonData
// if it's not Json String then skip this line
let jsonData = jsonString.data(using: .utf8)
// Try to convert it to json object
do {
let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as! [String : Any]
// now you can try to parse your json
} catch let error as NSError {
print(error.localizedDescription)
}
Or as #Jay mentioned use Swiftyjson

Parse JSON in Swift3

Using below code to parse JSON , facing issue
let result = "{
status = ok;
token = XXXXX;
}"
do {
let json = try JSONSerialization.jsonObject(with: (result as? Data)! , options: JSONSerialization.ReadingOptions())
print("Further data \(json)")
} catch {
print(error)
}
}
Facing below exception:
Could not cast value of type '__NSDictionaryI' (0x111789238) to
'NSData' (0x1117882e8). (lldb)
Any help is really appreciated.
First, JSON format is not correct. It should as
{
"status":"ok",
"token":"XXXXX"
}
Second, You are trying typecast string into NSData which is not possible. Issue is at
(result as? Data)!
Rather you should do it like this:
let resultData = result.data(using: String.Encoding.utf8)

Resources