Parse JSON in Swift3 - ios

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)

Related

jsonObject(with: data) succesfully reading valid json, but not returning valid json

I am dealing with some issues with the following code:
let session = URLSession.shared
session.dataTask(with: request) { data, response, error in
if let data = data {
let string1 = String(data: data, encoding: String.Encoding.utf8) ?? "Data could not be printed"
print(string1)
do {
if let jsonData = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
print("success")
print(jsonData as AnyObject)
}
} catch {
print(error.localizedDescription)
}
}
}.resume()
When I print out string1 it is valid json and the line print("success") gets executed. However, when it reaches print(jsonData as AnyObject) the output is similar to json, but there are = in place of : and () in place of []. In addition to this, some of the keys aren't even strings. It looks as follows:
(
{ "build_path" = "<null>";
city = "<null>";
cm = "<null>";
country = "<null>";
}, {
//similar to above
}
)
(the values are actually currently null)
I'm not really sure why this is happening so any help is appreciated. Thanks.
Remove as AnyObject in print(jsonData as AnyObject). It will print in the format you are expecting.
I looked through some old code, so try with the following line for the JSONSerialization part:
if let jsonData = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:Any]
I got the correct result when just:
print(jsonData)
Hope this helps.

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

Unable to get the value of JSON - Swift

I tried to get the value of "seed" from json response. But i am getting nil.
Json Response:
{
"response": {
"params": {
"rows": "20",
"defType": "abc",
"seed": "381786611"
}
}
}
Swift Parsing:
if let responseHeader:AnyObject = object?["response"] as? NSDictionary {
if let t = (responseHeader["params"] as? NSDictionary){
let t1 = t["seed"] as? String
println("result is \(t1)") // This returns nil
}
}
Json Parsing
func processJsonToDictionary(object:AnyObject?) -> AnyObject?{
if object != nil {
if let data: AnyObject = object {
var parseError: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(object as NSData!, options: NSJSONReadingOptions.MutableContainers, error: &parseError) as? NSDictionary
if(parseError != nil){
return parseError
}
else{
return jsonResult
}
}
}
return nil
}
I am not able to get the value of t1. it always returns nil.
How can i get the value.
Also, I put a breakpoint and tried to print the value of t1. But the Xcode Keeps crashing. Why?
I think the major problem here is only accessing a JSON object in swift.
var error: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
let resp = jsonDict["response"] as? NSDictionary
let params = resp?["params"]?["seed"]
let seed = params!! as NSString
This is just to show you how a JSON object is accessed in swift. You can ofcourse change it according to your needs to remove unwanted Optional Chaining.
For easy JSON manipulation in Swift you could try this little library. It seems pretty easy and you could do this:
var dictionary: [String: AnyObject]!
if let json = NKJSON.parse(yourNSDataObject) {
dictionary <> json[NKJSON.rootKey]
}
First confirm that the response which you are getting is in json format or in string format.
For json parsing you can use swifty json pod

Resources