How to parse data from server? [duplicate] - ios

This question already has answers here:
Correctly Parsing JSON in Swift 3
(10 answers)
Closed 5 years ago.
I am getting data like {"OTP":"5480"} in a string named responseString, How can I uset it.
My Code is.
#IBAction func signupButton() {
var request = URLRequest(url: URL(string:"http://122.166.215.8:8090/RESTMVC/validateMobileNumber")!)
request.httpMethod = "POST"
let mobileNumberString : String = self.mobileNumberTextfield.text!
let postString = ["mobileNumber":mobileNumberString]
request.httpBody = try! JSONSerialization.data(withJSONObject: postString, options:.prettyPrinted)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
var recived = [UInt8]()
recived.append(contentsOf: data)
print(responseString!)
DispatchQueue.main.async(execute: {
self.performSegue(withIdentifier: "OTPView", sender: nil)
});
}
task.resume()
}
and I want to change that string into Array. Or is there any way in which I can get Array directly on the place of String?

To access value of "OTP" you need to parse your response string and convert it in Json dictionary you can achive this using following code, just pass your response data in JSONSerialization.jsonObject(with: data, options: .allowFragments)
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! Dictionary<String, Any>
if let otpValue = json["OTP"] {
print("Otp value : \(otpValue)")
}
} catch {
// Handle Exception
}

You can get otp from dictionary like below.
print(responseString["OTP"])

Related

Swift 4 - When sending POST request to localhost, my URLRequest sends the JSON data with the dictionary as a key

Seems like a simple error, but I cannot resolve it for some reason:
let parameters = ["user_id":usernameTF.text!, "password": passwordTF.text!]
let jsonData = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
print(parameters)
print(jsonData!)
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField:"Accept")
request.httpMethod = "POST"
debugTV.text = "\(parameters["user_id"]!)"+"\(parameters["password"]!)"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options:[])
// pass dictionary to nsdata object and set it as request body
print(request.httpBody!)
} catch let error {
print(error.localizedDescription)
}
let task = session.dataTask(with: request) { (data, response, error) in
guard error == nil else {
return
}
guard let data = data else {
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
}
let responseString = String(data: data, encoding: .utf8)
print(responseString!)
}
when see the NodeJS debug window, my request body is
req.body = { '[password: "test", user_id: "test"]':'' }
how can I convert the request data into a JSON object?

Swift make a http request response as array

I have got this swift http request
var request = URLRequest(url: URL(string: "http://www.web.com/ajax/logreg.php")!)
request.httpMethod = "POST"
let pass = pass_text_field.text!.addingPercentEncoding(withAllowedCharacters: .queryValueAllowed)!
let postString = "app_reg_pass=\(pass)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(error!)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { print("statusCode should be 200, but is \(httpStatus.statusCode)")
print(response!)
}
let responseString = String(data: data, encoding: .utf8)
print(responseString!)
}
task.resume()
Reponse string:
Array
(
[0] => 1
[1] => Murad
)
And my response to this code is array.But when i try to treat response as array it gives me an error.How can i turn response into array so i can do this
response[0]?
Your result is most likely coming in as a JSON object, so you need to deserialize it before you can use the results.
do {
let jsonData = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [Any]
print(jsonData[0] as! Int) // should print "1"
print(jsonData[1] as! String) // should print "Murad"
} catch {
print("An error occurred")
}

HTTP POST (IOS)

I need to do an HTTP POST for a page that simply returns a literal (which can be "OK" or "ERROR") I have a web tutorial that shows how to do this and it returns a JSON, I follow the tutorial and it works perfectly .
My problem is exactly there ... it returns a JSON and what my site returns is not a JSON but a simple literal ..
How do I get this literal that the site is returning ... I've tried several changes in the code below but without success.
let parameters = ["username": "#kilo_loco", "tweet": "HelloWorld"]
guard let url = URL(string: "http://xxxxxxxxxx.com/ola.php") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
//request.addValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else { return }
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print ("*******")
print(response)
}
//print(data as Any)
if let data = data {
print("** TESTE **")
print(data)
//do {
// let json = try JSONSerialization.jsonObject(with: data, options: [])
//print(json)
//} catch {
// print(error)
// }
}
}.resume()
The Last "Print (data) returns the size in bytes and not the contents of the literal ..
You are missing parse Data to JSON Object, I think you have that code almos there but commented
do {
let json:AnyObject? = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json{
print(parseJSON)
}
}
Hope this helps you

iOS Swift POST param and body

I'm trying to POST a key parameter and a JSON dictionary body to an API but for some reason it won't work.
Here's my work so far.
#IBAction func POST(_ sender: Any) {
let url = URL(string: "http://apilink.com/updateProfile&=param")!
let jsonObject = ["FName":"Tarik",
"LName":"Salama"]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject, options: [])
var request = URLRequest(url: url)
request.httpMethod = "post"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
print("error:", error)
return
}
do {
guard let data = data else { return }
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else { return }
print("json:", json)
} catch {
print("error:", error)
}
}
task.resume()
}
I get this error when I click the POST button:
error: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
What am I doing wrong?
I tried changing some stuff around after I checked some other threads like putting the parameter and the data dictionary into a key:value dictionary but the API responded and said that the data is invalid which means the whole thing was sent in an incorrect format.
Note: I'm not allowed to use 3rd party libraries like Alamofire and the API link is working fine as shown in the screenshot.
you can check the problem by printing the response data
do {
guard let data = data else { return }
print(String(data: data, encoding: .utf8) ?? "No Conversion") //Print Here
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else { return }
print("json:", json)
} catch {
print("error:", error)
}
look at the 'Print Here' line. I believe the response is not a valid json so when you try to parse the data to JSOn it always ends up in catch block.

HTTP Request in Swift with POST method

I'm trying to run a HTTP Request in Swift, to POST 2 parameters to a URL.
Example:
Link: www.thisismylink.com/postName.php
Params:
id = 13
name = Jack
What is the simplest way to do that?
I don't even want to read the response. I just want to send that to perform changes on my database through a PHP file.
The key is that you want to:
set the httpMethod to POST;
optionally, set the Content-Type header, to specify how the request body was encoded, in case server might accept different types of requests;
optionally, set the Accept header, to request how the response body should be encoded, in case the server might generate different types of responses; and
set the httpBody to be properly encoded for the specific Content-Type; e.g. if application/x-www-form-urlencoded request, we need to percent-encode the body of the request.
E.g., in Swift 3 and later you can:
let url = URL(string: "https://httpbin.org/post")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
let parameters: [String: Any] = [
"id": 13,
"name": "Jack & Jill"
]
request.httpBody = parameters.percentEncoded()
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else { // check for fundamental networking error
print("error", error ?? URLError(.badServerResponse))
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
// do whatever you want with the `data`, e.g.:
do {
let responseObject = try JSONDecoder().decode(ResponseObject<Foo>.self, from: data)
print(responseObject)
} catch {
print(error) // parsing error
if let responseString = String(data: data, encoding: .utf8) {
print("responseString = \(responseString)")
} else {
print("unable to parse response as string")
}
}
}
task.resume()
Where the following extensions facilitate the percent-encoding request body, converting a Swift Dictionary to a application/x-www-form-urlencoded formatted Data:
extension Dictionary {
func percentEncoded() -> Data? {
map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed: CharacterSet = .urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
And the following Decodable model objects facilitate the parsing of the application/json response using JSONDecoder:
// sample Decodable objects for https://httpbin.org
struct ResponseObject<T: Decodable>: Decodable {
let form: T // often the top level key is `data`, but in the case of https://httpbin.org, it echos the submission under the key `form`
}
struct Foo: Decodable {
let id: String
let name: String
}
This checks for both fundamental networking errors as well as high-level HTTP errors. This also properly percent escapes the parameters of the query.
Note, I used a name of Jack & Jill, to illustrate the proper x-www-form-urlencoded result of name=Jack%20%26%20Jill, which is “percent encoded” (i.e. the space is replaced with %20 and the & in the value is replaced with %26).
See previous revision of this answer for Swift 2 rendition.
Swift 4 and above
func postRequest() {
// declare the parameter as a dictionary that contains string as key and value combination. considering inputs are valid
let parameters: [String: Any] = ["id": 13, "name": "jack"]
// create the url with URL
let url = URL(string: "www.thisismylink.com/postName.php")! // change server url accordingly
// 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
// add headers for the request
request.addValue("application/json", forHTTPHeaderField: "Content-Type") // change as per server requirements
request.addValue("application/json", forHTTPHeaderField: "Accept")
do {
// convert parameters to Data and assign dictionary to httpBody of request
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
return
}
// create dataTask using the session object to send data to the server
let task = session.dataTask(with: request) { data, response, error in
if let error = error {
print("Post Request Error: \(error.localizedDescription)")
return
}
// ensure there is valid response code returned from this HTTP response
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode)
else {
print("Invalid Response received from the server")
return
}
// ensure there is data returned
guard let responseData = data else {
print("nil Data received from the server")
return
}
do {
// create json object from data or use JSONDecoder to convert to Model stuct
if let jsonResponse = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? [String: Any] {
print(jsonResponse)
// handle json response
} else {
print("data maybe corrupted or in wrong format")
throw URLError(.badServerResponse)
}
} catch let error {
print(error.localizedDescription)
}
}
// perform the task
task.resume()
}
For anyone looking for a clean way to encode a POST request in Swift 5.
You don’t need to deal with manually adding percent encoding.
Use URLComponents to create a GET request URL. Then use query property of that URL to get properly percent escaped query string.
let url = URL(string: "https://example.com")!
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
components.queryItems = [
URLQueryItem(name: "key1", value: "NeedToEscape=And&"),
URLQueryItem(name: "key2", value: "vålüé")
]
let query = components.url!.query
The query will be a properly escaped string:
key1=NeedToEscape%3DAnd%26&key2=v%C3%A5l%C3%BC%C3%A9
Now you can create a request and use the query as HTTPBody:
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = Data(query.utf8)
Now you can send the request.
Heres the method I used in my logging library: https://github.com/goktugyil/QorumLogs
This method fills html forms inside Google Forms.
var url = NSURL(string: urlstring)
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPBody = postData.dataUsingEncoding(NSUTF8StringEncoding)
var connection = NSURLConnection(request: request, delegate: nil, startImmediately: true)
let session = URLSession.shared
let url = "http://...."
let request = NSMutableURLRequest(url: NSURL(string: url)! as URL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
var params :[String: Any]?
params = ["Some_ID" : "111", "REQUEST" : "SOME_API_NAME"]
do{
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions())
let task = session.dataTask(with: request as URLRequest as URLRequest, completionHandler: {(data, response, error) in
if let response = response {
let nsHTTPResponse = response as! HTTPURLResponse
let statusCode = nsHTTPResponse.statusCode
print ("status code = \(statusCode)")
}
if let error = error {
print ("\(error)")
}
if let data = data {
do{
let jsonResponse = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions())
print ("data = \(jsonResponse)")
}catch _ {
print ("OOps not good JSON formatted response")
}
}
})
task.resume()
}catch _ {
print ("Oops something happened buddy")
}
All the answers here use JSON objects. This gave us problems with the
$this->input->post()
methods of our Codeigniter controllers. The CI_Controller cannot read JSON directly.
We used this method to do it WITHOUT JSON
func postRequest() {
// Create url object
guard let url = URL(string: yourURL) else {return}
// Create the session object
let session = URLSession.shared
// Create the URLRequest object using the url object
var request = URLRequest(url: url)
// Set the request method. Important Do not set any other headers, like Content-Type
request.httpMethod = "POST" //set http method as POST
// Set parameters here. Replace with your own.
let postData = "param1_id=param1_value&param2_id=param2_value".data(using: .utf8)
request.httpBody = postData
// Create a task using the session object, to run and return completion handler
let webTask = session.dataTask(with: request, completionHandler: {data, response, error in
guard error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}
guard let serverData = data else {
print("server data error")
return
}
do {
if let requestJson = try JSONSerialization.jsonObject(with: serverData, options: .mutableContainers) as? [String: Any]{
print("Response: \(requestJson)")
}
} catch let responseError {
print("Serialisation in error in creating response body: \(responseError.localizedDescription)")
let message = String(bytes: serverData, encoding: .ascii)
print(message as Any)
}
// Run the task
webTask.resume()
}
Now your CI_Controller will be able to get param1 and param2 using $this->input->post('param1') and $this->input->post('param2')
#IBAction func btn_LogIn(sender: AnyObject) {
let request = NSMutableURLRequest(URL: NSURL(string: "http://demo.hackerkernel.com/ios_api/login.php")!)
request.HTTPMethod = "POST"
let postString = "email: test#test.com & password: testtest"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){data, response, error in
guard error == nil && data != nil else{
print("error")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200{
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
}

Resources