how to retrive JSON data by using swift - json

I am retrieving datas from JSON by using swift. I am new to JSON. I don't how to retrieve this nested values. My previous question is Issue raised, while retriving datas from JSON by using swift . I got clarified. This is new to me. My JSON format is below. Kindly guide me.
JSON Response formats:
{
"salutation": {
"id": 1,
"salutation": "Mr"
},
"firstName": "AAA",
"middleName": "BBB",
"lastName": "C",
"employeeId": "RD484",
"station": {
"id": 86,
"stationCode": null,
"stationName": "DDD",
"subDivision": null,
"address": null
},
"subDivsion": {
"id": 11,
"divisionCode": "11",
"divisionDesc": "EEE",
"division": null
}
}
//My Attempt:
var maindict = NSDictionary() //Global declaration
var session = NSURLSession.sharedSession()
//now create the NSMutableRequest object using the url object
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST" //set http method as POST
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err) // pass dictionary to nsdata object and set it as request body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
self.maindict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as [String: AnyObject]
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
//println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
self.dataFromJSON() //METHOD CALLING
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
//println("AUTHENTICATION FAILED")
}
}
})
task.resume()
func dataFromJSON()
{
println("Main Dict Values: \(maindict)") //PRINTING ALL VALUES
let dataArray = maindict["firstName"] as? [String:AnyObject]
println("FirstName Values: \(dataArray)") // PRINTING NIL VALUES
}

Your data structure does not begin with an array this time, but with a Dictionary. Your structure is like is:
root Dictionary -> "salutation" -> Dictionary
root Dictionary -> "station" -> Dictionary
root Dictionary -> "subDivsion" -> Dictionary
Let's say you want to access the "id" of "salutation", then:
// Just an exemple of how to download, surely you have your own way
func getJSON(url: NSURL) {
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: url)
let task = session.dataTaskWithRequest(request){
(data, response, downloadError) -> Void in
if let error = downloadError {
println(error.localizedDescription)
} else {
var jsonError: NSError?
// cast the result as a Dictionary
if let dict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as? [String: AnyObject] {
// print the dictionary to check contents
println(dict)
if let salutationDictionary = dict["salutation"] as? [String: AnyObject] {
if let id = salutationDictionary["id"] as? Int {
println(id)
}
}
}
if jsonError != nil {
println(jsonError)
}
}
}
task.resume()
}
EDIT:
My friend, your code was a mess... I suggest to you to do some cleaning when you've got errors, it helps to debug. Anyway, here's a corrected version of your new code. Pay attention to how maindict is declared on the first line. Also, you had one unnecessary call to NSJSONSerialization, I simplified it. Note: for the sake of the example, I've included your dataFromJSON function code directly inside if let parseJSON ..., but of course it doesn't mean you have to do the same.
var maindict: [String: AnyObject]?
var session = NSURLSession.sharedSession()
//let parameters = ...
let request = NSMutableURLRequest(URL: your_url!)
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var err: NSError?
maindict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &err) as? [String: AnyObject]
if err != nil {
println(err!.localizedDescription)
} else {
if let parseJSON = maindict {
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
println("Main Dict Values: \(maindict)")
let firstName = maindict!["firstName"] as? String
println("FirstName: \(firstName)")
}
else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
Please pay attention to the details and study my modifications by comparing with your attempt. My answer has been tested on my own server and it works, so you can use it as a working base.

The easiest way to do this is to use a library.
1) You can use swiftyJSON. It uses the objective C JSON parsing library.
https://github.com/SwiftyJSON/SwiftyJSON
2) If you want a library which uses a pure swift parser try JSONSwift. The readme on github shows how you can retrieve nested values from the JSON file. And integrating it in your project just requires you to import a single file. https://github.com/geekskool/JSONSwift

Related

How to POST data from multiple view controllers to server with JSON using SWIFT

I need help with combining data collected from firstVC, secondVC, and thirdVC and serializing those in the fourthVC.
This link helps with one VC but I have to send only ONE FILE of JSON DATA to the server.
How to create and send the json data to server using swift language
The other method is passing a dictionary array from firstVC, secondVC, and thirdVC to the fourthVC and from the fourthVC convert the dictionaries into JSON. But i don't know how to do that.
I used the format from the answer provided in the link above, but if you need additional info, I will gladly cooperate. Thanks!
PS. Please give me useful comments that will help in any way. I need the code and not feedbacks like doing my own research and such cause I have been stressing about this for nearly a month now.
This is the UserDefault keys
if let AC = UserDefaults.standard.value(forKey: "Acc") as? String {
labeltext.text = "\(AC)"
}
if let TY = UserDefaults.standard.value(forKey: "Taxyear") as? String {
taxtext.text = "\(TY)"
}
if let BB = UserDefaults.standard.value(forKey: "Bsb") as? String {
bsbtext.text = "\(BB)"
}
Here is my JSON code
#IBAction func save(_ sender: Any){
typealias JSONDictionary = [String:Any]
let parameters = ["BankAccountNumber": "Acc", "Tax Year": "Taxyear", "my-bsb": "Bsb"]
let url = URL(string: "https://server:port/")! //change the url
//create the session object
let session = URLSession.shared
//now create the URLRequest object using the url object
var request = URLRequest(url: url)
request.httpMethod = "POST" //set http method as POST
let valid = JSONSerialization.isValidJSONObject(parameters) // true
print (valid)
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
} catch let error {
print(error)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// create dataTask using the session object to send data to the server
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
// handle json...
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
let alertMessage = UIAlertController(title: "Saved!", message: "We have recorded your information", preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title:"Okay", style: UIAlertActionStyle.default, handler: nil)
alertMessage.addAction(action)
self.present(alertMessage, animated: true, completion: nil)
}
I solved it by first storing them in a variable
var TITLE = UserDefaults.standard.value(forKey: "Title")
var GN = UserDefaults.standard.value(forKey: "GivenNames")
var LN = UserDefaults.standard.value(forKey: "LastName")
Then I placed them in a parameter and that's done. It was so obvious that I can't believe I didn't solve it sooner
#IBAction func save(_ sender: Any){
let parameters = ["Tax Year": TaxYear, "Title": TITLE, "first-name": GN, "sur-name": LN]

HTTP Request GET JSON and read data

i have a problem by a code of me in swift. I do a request to webserver by httpMethod POST. This request is ok. I get a response and data inside the data value. The data looks like JSON
{"pushValues": {"devicePushGlobal":"1","devicePushNewProducts":"1","devicePushNewOffer":"1"}}
Then I will load this response data to set buttons based on the response data. But i fail to write this code. Can someone help me please? :)
Error Code
Cannot invoke 'jsonObject' with an argument list of type '(with: NSString)'
// i tested with other options but i always fail :-(
I comment the error in the code ....
let url = "https://URL.php"
let request = NSMutableURLRequest(url: NSURL(string: url)! as URL)
let bodyData = "token=" + (dts)
request.httpMethod = "POST"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main) {
(response, data, error) in
// here i get the result of
// {"pushValues": {"devicePushGlobal":"1","devicePushNewProducts":"1","devicePushNewOffer":"1"}}
var str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
var names = [String]()
// here i will get each value of pushValues to add to the array names
do {
if let data = str,
// ... and here is the error code by xcode ::: ==> Cannot invoke 'jsonObject' with an argument list of type '(with: NSString)'
// i tested with other options but i always fail :-(
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let blogs = json["pushValues"] as? [[String: Any]] {
for blog in blogs {
if let name = blog["devicePushGlobal"] as? String {
print(name)
names.append(name)
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
// names array is empty
print(names)
}
Thank you for your help
You shouldn't decode the JSON response into an NSString using var str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue). JSONSerialization.jsonObject() expects a Data object as an input argument, so just safely unwrap the optional data variable and use that as the input argument:
if let responesData = data, let json = try JSONSerialization.jsonObject(with: responseData) as? [String: Any], let blogs = json["pushValues"] as? [String: Any]
The full code using native Swift types:
...
let request = URLRequest(url: URL(string: url)!)
...
URLSession.shared.dataTask(with: request, completionHandler: {
(response, data, error) in
var names = [String]()
do {
if let responseData = data, let json = try JSONSerialization.jsonObject(with: responseData) as? [String: Any], let blogs = json["pushValues"] as? [String: Any]{
if let name = blog["devicePushGlobal"] as? Int {
print(name)
names.append(name)
}
if let newProducts = blog["devicePushNewProducts"] as? Int{}
if let newOffers = blog["devicePushNewOffers"] as? Int{}
}
} catch {
print("Error deserializing JSON: \(error)")
}
// names array is empty
print(names)
}).resume()

Getting array instead of dictionary

I did't use third-party files for calling the API, here is the code:
func CallWebService(_ methodType: NSString, methodName: NSString, inputDict: NSDictionary, completion: #escaping (_ result: [String:AnyObject]) -> Void, failure:(_ failurMSG: NSString)->())
{
do {
let data: Data = try JSONSerialization.data(withJSONObject: inputDict, options: [])
//create request
let tmpString: String = "\(kBaseUrl)\(methodName)"
let urlString :String = tmpString.addingPercentEncoding( withAllowedCharacters: CharacterSet.urlQueryAllowed)!
let urlRequest = NSMutableURLRequest(url: URL(string: urlString)!)
urlRequest.httpMethod = methodType as String
urlRequest.httpBody = data
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task : URLSessionDataTask! = URLSession.shared.dataTask(with: urlRequest as URLRequest, completionHandler: {
(data, response, error) in
if let _ = error
{
DispatchQueue.main.async(execute: {
})
}else{
do {
let dict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:AnyObject]
completion(dict)
}catch{
}
}
})
task.resume()
} catch {
DispatchQueue.main.async(execute: {
})
failure("Something goes wrong please try again.")
}
}
While I'm hitting API I got the below response:
["status": success, "category": {
"file_image" = "http://abcds.com/cphp/26/uploads/pdf1.png";
"file_name" = "1 \U0645\U0644\U0641 \U0627\U062e\U062a\U0628\U0627\U0631";
"file_path" = "http://hghg/images/2311201663231Michael20plat20du20jour20correctd.pdf";
id = 2;
"sub_name" = "P12 \U0641\U0631\U0639\U064a\U0629";
}]
This is not the correct format, what am I missing?
I need the output to be:
{"status": success, "category": [
"file_image" = "http://abcds.com/cphp/26/uploads/pdf1.png";
"file_name" = "1 \U0645\U0644\U0641 \U0627\U062e\U062a\U0628\U0627\U0631";
"file_path" = "http://hghg/images/2311201663231Michael20plat20du20jour20correctd.pdf";
id = 2;
"sub_name" = "P12 \U0641\U0631\U0639\U064a\U0629";
]
}
It looks to me like you ARE getting a dictionary.
EDIT:
In fact, the fact that your code is force-casting the JSON data to type [String:AnyObject] proves that the results are a dictionary. If they weren't, the force-cast line would crash:
let dict = try JSONSerialization.jsonObject(with: data!,
options: .allowFragments) as! [String:AnyObject]
(The as! [String:AnyObject] part of that line says "I am positive that the value can be cast to the type [String:AnyObject]. Please crash my program if not.)
Try adding this to your code:
print("dict type =" + String(describing:type(of:dict)))
I bet you get
dict type = Dictionary<String:AnyObject>

How to add multiple paramaters[String,Dictionary] in a dictionary using swift?

I am building iOS Application using Swift.I am using XCODE version 6.3.
I want to post data to server using JSON.For that i created a dictionary for performing the following operation.
//This is my dictionary right now
var parameters = ["authenticity_token":name,"platform":"mobileApp", "email": userEmail, "password": userPassword,"remember_me":"1"]
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err)
I want to pass data as the format shown below.
{"authenticity_token":"token","platform":"mobileApp",
"user":{"email":"email_id", "password":"123456",
"remember_me":"1"}}
Right now parameter dictionary in the Format
[platform: mobileApp, authenticity_token: a1oj3olt5jn169LHn59ZbfbrBVUyov7sDVHlOl+2YzE=, email: su#gmail.com, remember_me: 1, password: samrat]
order of the paramater also changed.
I want to pass to my dictionary.
Or is there any possibility to add two dictionaries.
This is my code for posting data to server.I have another confusion whether it is correct or not.
func postData()
{
let name = defaults.stringForKey("secretKey")
var parameters = ["authenticity_token":name,"platform":"mobileApp", "email": userEmail, "password": userPassword,"remember_me":"1"]
println("Dic\(parameters)")
let url = NSURL(string: "http://behance.moblearn.net/users/sign_in")
var session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err)
let jsonStr = NSString(data: request.HTTPBody!, encoding: NSUTF8StringEncoding)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
println("Post Method reached")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
if let parseJSON = json {
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
}
I am in deep trouble.I am Beginner in swift.Help will be appreciated.
Do like this:
let innerDict = ["email": "email_id", "password": "123456", "remember_me": "1"]
let mainDict = ["authenticity_token": "token", "platform": "mobileApp", "user": innerDict]

How to change JSON POST request to handle HTTPS

Below is my login function. It's a JSON POST request and before, when the URL was http, it worked flawlessly. I attached a JSON filled with the username/password of the user. Today we added a SSL Certificate and after switching the URL to https, it produced this error:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
I'm not really sure what's going on. I typed that error into google and didn't get any where. I appreciate any help, thank you!
func login(params : Dictionary<String, String>, url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if response != nil {
if response.isKindOfClass(NSHTTPURLResponse) {
httpResponse = response as NSHTTPURLResponse
if let authorizationID = httpResponse.allHeaderFields["Authorization"] as String! {
Locksmith.saveData(["id":authorizationID], forUserAccount: currentUser, inService: "setUpAuthorizationId")
}
else {
println("Failed")
}
}
}
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr!)'")
postCompleted(succeeded: false, msg: "Error")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
if let status = parseJSON["status"] as? String {
if let extractData = parseJSON["data"] as? NSDictionary {
let extractUserId:Int = extractData["id"] as Int
userId = extractUserId
}
if status == "success" {
postCompleted(succeeded: true, msg: "Logged in.")
} else {
let failMessage = parseJSON["message"] as? String
postCompleted(succeeded: false, msg: failMessage!)
}
}
return
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
postCompleted(succeeded: false, msg: "Error")
}
}
})
task.resume()
}
Using This awesome article I was able to fix my problem. All I needed to do was add:
NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate
after my class name, and then add these two delegates:
func URLSession(session: NSURLSession,
didReceiveChallenge challenge:
NSURLAuthenticationChallenge,
completionHandler:
(NSURLSessionAuthChallengeDisposition,
NSURLCredential!) -> Void) {
completionHandler(
NSURLSessionAuthChallengeDisposition.UseCredential,
NSURLCredential(forTrust:
challenge.protectionSpace.serverTrust))
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
var newRequest : NSURLRequest? = request
println(newRequest?.description);
completionHandler(newRequest)
}
after that in my actual request I just needed to change:
var session = NSURLSession.sharedSession()
to:
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
hope this helps someone!!