Parsing the JSON Data in Swift 2 - ios

I am parsing the data and I am getting the responseString also.But my problem is I want to convert it into dictionary and then I want to get the values from that jsonObject.
But I am unable to get that.
My Code is as follows
func loginRequest(url:String, withParams params: [String: String?], postCompleted : (succeeded: Bool, msg: String) -> ()){
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
var bodyData = ""
for (key,value) in params{
if (value == nil){ continue }
let scapedKey = key.stringByAddingPercentEncodingWithAllowedCharacters(
.URLHostAllowedCharacterSet())!
let scapedValue = value!.stringByAddingPercentEncodingWithAllowedCharacters(
.URLHostAllowedCharacterSet())!
bodyData += "\(scapedKey)=\(scapedValue)&"
}
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
let task = session.dataTaskWithRequest(request,
completionHandler: {data, response, error -> Void in
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
postCompleted(succeeded: true, msg: dataString! as String)
print(dataString!)
if let datas = dataString!.dataUsingEncoding(NSUTF8StringEncoding) {
do{
let json = try NSJSONSerialization.JSONObjectWithData(datas, options: []) as? [String:AnyObject]
//return json
print(json)
}
catch
{
print("Something went wrong")
}
}
})
task.resume()
}
I am calling that method like this
self.loginRequest("http://stream.gsr-india.com:8080/pgn_service/REST/WebService/GetUserDetails",
withParams: ["first_name":firstNameTextField.text,"last_name":lastNameTextField.text , "application_id":uniqueIdTextField.text])
{
(succeeded: Bool, msg: String) -> () in
if(succeeded) {
if msg == "0"
{
//Incorrect data...
}
else
{
//The login it's ok...
}
}
}
Can anyone Please help me to resolve that.
Thanks In Advance.

Change method declaration to
func loginRequest(url:String, withParams params: [String: String?], postCompleted : (succeeded: Bool, msg: NSDictionary?) -> ()){
then change the task handler to
let task = session.dataTaskWithRequest(request,
completionHandler: {data, response, error -> Void in
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(dataString!)
do{
let json = try NSJSONSerialization.JSONObjectWithData(datas, options: []) as? [String:AnyObject]
postCompleted(succeeded: true, msg: json)
print(json)
}
catch {
print("Something went wrong")
}
}
})
change the callback to
(succeeded: Bool, msgDict: NSDictionary?) -> () in
if let dict = msgDict {
// call any value like dict["error"] etc
}

Related

How to use if condition from using the console output?

How to use if condition from using the console output?
let myURL = URL(string: "http://www.digi.com/laravel_api_demo/api/demoapipost")
let request = NSMutableURLRequest(url: myURL!)
request.httpMethod = "POST"
let postString = "username=rahul"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
guard let _: Data = data, let _:URLResponse = response, error == nil else {
print("error")
return
}
if let dataString = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
{
print(dataString)
}
}
task.resume()
console output
How to use this output {"status":"No"}
I want to use if condition using status value.
Example:
if status == "YES"
{
print("Entered")
}
else
{
print("Not Entered")
}
Try to convert your String to Dictionary format.
func convertToDictionary(from text: String) -> [String: String]? {
guard let data = text.data(using: .utf8) else { return nil }
let anyResult = try? JSONSerialization.jsonObject(with: data, options: [])
return anyResult as? [String: String]
}
let string1 = "{\"status\":\"No\"}"
let dictionary1 : [String : String] = convertToDictionary(from: string1)!
if dictionary1["status"] == "No"
{
print("No")
}
else
{
print("yes")
}
As per, #moritz suggestion, you having JSON Data, so instead of converting to String, you can directly convert your data to [String : String]
if let respJSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : String]
{
if respJSON["status"] == "No"
{
print("No")
}
else
{
print("yes")
}
}

How to fetch JSON data from a url using URLSession?

I am working on an iOS application in which I have to fetch data from this url .
As I can see this url contain JSON data so here should I need to parse it or not I am not getting it how to get this JSON data.
Here is my code.
import UIKit
import SwiftyJSON
typealias ServiceResponse = (ApiResponseData, NSError?) -> Void
class ApiManager: NSObject {
var session:URLSession? = nil
var urlRequest:URLRequest? = nil
override init(){
super.init()
urlRequest = URLRequest(url: URL(string:"https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json")!)
urlRequest?.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
session = URLSession(configuration: .default)
}
func callRestApiToFetchDetails(onCompletion: #escaping ServiceResponse) {
let task = session?.dataTask(with: urlRequest!, completionHandler: {data, response, error -> Void in
print("Response = \(data)")
do {
let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
// Do Stuff
print("\(jsonData)")
} catch {
// handle error
print("Error in parsing - \(error)")
}
})
task?.resume()
}
}
But I am getting error in parsing.
You web service response is String.Encoding.ascii that convert into
String.Encoding.utf8 after you have to convert through
NSDictionary JSONSerialization.
Try this method to work.
let url = "https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json"
URLSession.shared.dataTask(with: URL(string: url)!) { (data, res, err) in
if let d = data {
if let value = String(data: d, encoding: String.Encoding.ascii) {
if let jsonData = value.data(using: String.Encoding.utf8) {
do {
let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as! [String: Any]
if let arr = json["rows"] as? [[String: Any]] {
debugPrint(arr)
}
} catch {
NSLog("ERROR \(error.localizedDescription)")
}
}
}
}
}.resume()

Calling a function and wait for its completion

i have this class and its func
class DataUsuarios {
func update(completionHandler : ((isResponse : Array<JSON>) -> Void)) {
//CODE
completionHandler(isResponse: jsn)
}
}
and i call it with this
let data = DataUsuarios()
data.update{(isResponse) -> Void in
self.datos = isResponse
}
and it works as it should..
Now i have this class and function that i made
import Foundation
class Post{
func makeRequest(param : String, url : String, completionHandler : ((succeeded: Bool, msg: String? , crypted : String?) -> Void)) {
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
let params : Dictionary<String, String> = ["VAL": param]
let session = NSURLSession.sharedSession()
session.configuration.timeoutIntervalForRequest = 3 //3 segundos timeoutRequest
session.configuration.timeoutIntervalForResource = 5 //5 segundos timeoutResource
request.HTTPMethod = "POST"
do{
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
}catch let err as NSError {
print(err.localizedDescription)
print("Error could not make request'")
completionHandler(succeeded: false, msg: "Error al interpretar JSON" , crypted: nil)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
print("Response: \(response)")
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)")
var json : NSDictionary?
do{
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
}catch let err as NSError {
print(err.localizedDescription)
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: '\(jsonStr)'")
completionHandler(succeeded: false, msg: "Error en POST", crypted: nil)
}
if let parseJSON = json {
if let encrypted = parseJSON["encriptado"] as? String {
let decrypted = encrypted.aesDecrypt()
let datosDecrypted: NSData = decrypted.dataUsingEncoding(NSUTF8StringEncoding)!
var jsonLogin:NSDictionary!
do{
jsonLogin = try NSJSONSerialization.JSONObjectWithData(datosDecrypted , options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
}catch let err as NSError {
print(err.localizedDescription)
print("Error could not make request'")
completionHandler(succeeded: false, msg: "Error" , crypted: nil)
}
if ( jsonLogin.valueForKey("success") != nil ) {
if let successNumber = jsonLogin.valueForKey("success") as! Int! {
print("Success: " , successNumber);
completionHandler(succeeded: true, msg: nil, crypted: decrypted)
}
}
completionHandler(succeeded: false, msg: "Error Success", crypted: nil)
}
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: \(jsonStr)")
completionHandler(succeeded: false, msg: "Error", crypted: nil)
}
})
task.resume()
}
}
but i don't know how to call it and get the completionHandler values
let post = Post()
post.makeRequest(cad, url: Constants.Static.server+"url.php" { succeeded, msg, crypted) -> Void in
}
Hope you can help! :)
Perhaps you want dispatch_async()?:
func makeRequest(param : String, url : String, completionHandler : ((succeeded: Bool, msg: String? , crypted : String?) -> ())) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
println("This is run on the background queue")
//CODE
dispatch_async(dispatch_get_main_queue(), 0), {
println("This is run on the main queue, after the previous block")
completionHandler(succeeded: true, msg: nil, crypted: decrypted)
}
}
}
Ok, i found it..
post.makeRequest(cad, url: Constants.Static.server+"url.php" ){(succedded : Bool, msg : String?, crypted:String? ) in
if(succedded){
// CODE USING CRYPTED
}else {
// CODE USING MSG
}
}

Use Type T as parameter in completion handler

I have written a function for a URL request. This contains a completion handler that returns a dictionary of [String: AnyObject] that is fetched from the URL.
The code for this is:
func getDataAsyncFromURLRequest(url: NSURL, completion: ([String : AnyObject]) -> ()) {
let request = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error != nil {
print("error=\(error)")
return
}
else {
let datastring = NSString(data: data!, encoding: NSUTF8StringEncoding)
if let data = datastring!.dataUsingEncoding(NSUTF8StringEncoding) {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! [String : AnyObject]
completion(json)
} catch {
print("json error: \(error)")
}
}
}
}
task.resume()
}
In some cases, however, I will receive an array of [String : AnyObject] and not the dictionary. So instead of making a duplicate function that takes the array of dictionaries as parameter for the completion handler, I though it was possible to do like this
func getDataAsyncFromURLRequest<T>(url: NSURL, completion: (T) -> ()) {
// code here
}
... and then do like this let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! T, but that gives me this error: Cannot invoke 'getDataAsyncFromURLRequest' with an argument list of type '(NSURL, completion: (_) -> ())'
What would be the best way to make the completion handler accept a parameter with a type decided at runtime, if possible at all?
It's very easy why don't you use AnyObject
func getDataAsyncFromURLRequest(url: NSURL, completion: (AnyObject) -> ()) {
let request = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error != nil {
print("error=\(error)")
return
}
else {
let datastring = NSString(data: data!, encoding: NSUTF8StringEncoding)
if let data = datastring!.dataUsingEncoding(NSUTF8StringEncoding) {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
completion(json)
} catch {
print("json error: \(error)")
}
}
}
}
task.resume()
}
And result of JSONObjectWithData can be [AnyObject] (Array) or [String:AnyObject] and tree of those items.
So after got result, you can also check type of result in completion block
Like this
if result is [String:AnyObject]
...
else if result is [AnyObject]
...
else
//throw error : because then it is not JSON

cannot invoke 'jsonObjectWithData'

I cannot figure out how to solve this issue.
This comes from a youtube tutorial to build a simple Weather App.
The tutorial was uploaded in March 2015 and therefor written in a previous version of Swift, there it worked, with the current Swift 2 it doesn't.
The error I get is: "cannot invoke 'jsonObjectWithData' with an argument list of type '(NSData, options: nil, error: NSError)'"
func getWeatherData(urlString:String) {
let url = NSURL(string: urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!){ (data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
self.setLabels(data)
})
}
task.resume()
}
func setLabels(weatherData: NSData) {
var jsonError: NSError
let json = NSJSONSerialization.JSONObjectWithData(weatherData, options: nil, error: jsonError)
if let name = json["name"] as? String {
self.ResultLabel.text = name
}
}
if you want to get this code ready for Swift 2, you have to run the JSONParser with try and catch possible errors.
private func httpGetRequest(request: NSURLRequest!, callback: (NSData?, String?) -> Void) {
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request){
(data, response, error) -> Void in
if error != nil {
callback(nil, error!.localizedDescription)
} else {
callback(data, nil)
}
}
task!.resume()
}
func setLabels(weatherData: NSData) {
do {
let json = try NSJSONSerialization.JSONObjectWithData(weatherData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let name = json["name"] as? String {
self.resultLabel.text = name
}
} catch {
print(error)
self.resultLabel.text = "Lorem Ipsum"
}
}
func loadWeatherData() {
let weatherRequest = NSMutableURLRequest(URL: NSURL(string: "Your URL String goes here")!)
httpGetRequest(weatherRequest){
(data, error) -> Void in
if error != nil {
print("Error: \(error)")
} else {
self.setLabels(data!)
}
}
}
Hope that will help to solve your Problems.
Try this:
var jsonError: NSError?
let json = NSJSONSerialization.JSONObjectWithData(weatherData, options: nil, error: &jsonError)
in swift 3.0 and Swift 4.2
try this ...
do {
let jsonData = try JSONSerialization.data(withJSONObject: your array or dictionary, options: JSONSerialization.WritingOptions()) as Data
let json = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions(rawValue: UInt(0)))
}
catch
{
}
You need to pass the error pointer into NSJSONSerialization.JSONObjectWithData(...) with &.
let json = NSJSONSerialization.JSONObjectWithData(weatherData, options: nil, error: &jsonError) // &jsonError points to the NSErrorPointer of the NSError object
In swift 3 you can try this:
func setLabels(weatherData: NSData) {
do {
var jsonError: NSError
let json = try JSONSerialization.jsonObject(with: weatherData as Data, options: []) as! NSDictionary
if let name = json["name"] as? String {
self.ResultLabel.text = name
}
} catch {
}
}
In Swift 3, you can fix the same error with the code below:
do{
let jsonData = try JSONSerialization.jsonObject(with: (data)!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: AnyObject]
}catch{
print("Error while parsing JSON: Handle it")
}

Resources