swift - how to get JSON response from server - ios

I'm sending this data to a server and I would like it to respond. Tried this code but it doesn't work.
let parameters = [ "imie" : (imie), "nazwisko" : (nazwisko), "telefon" : (telefon), "adres" : (adres), "miasto" : (miasto), "kod" : (kod), /*"powiat" : (powiat), "wojewodztwo" : (wojewodztwo),*/ "opis" : (selectedvalue) ]
let url = URL(string: "http://www.hetman.pl/post1.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.setBodyContent(parameters)
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
if error != nil{
return
}
do{
let t = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print(t as? String)
} catch{
print("Error 43 -> \(error)")
}
}
Request is correct and server is processing data properly, but response gives me this error:
Error 43 -> Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 3." UserInfo={NSDebugDescription=Invalid value around character 3.}
So the question is, how do I get the data back from server?

Please check if response from this url is JSON only. You might be getting XML or string response.
Try below line if you are getting String response :
let stringResponse = String(data: data!, encoding: String.Encoding.utf8) as String!
Try below line if you are getting XML response :
let xmlDictionary = try XMLSerialization.xmlObject(with: data!) as? [String: Any]

Why there is to content type?
// code 3840, data.length = 1 byte, so empty and no error
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
Remove first content-type header field and try with only:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

Related

Send data to Airtables through a POST request with a json body

Im trying to send data to Airtables using its REST APIs based on the documentation. The part Im stuck is adding the parameters. It throws me an error saying "Invalid request: parameter validation failed. Check your request data".
The Curl according to the doc as bellow.
My partially done code as bellow.
let table_name = "Diet%20Plan"
let base_id = "appmrzybooFj9mFVF"
let token = "SomeID"
// prepare json data
let json: [String: String] = ["Food Type": "Minseee",
"Person Name": "Rabiit Con"]
// create the url with URL
let url = URL(string: "https://api.airtable.com/v0/\(base_id)/\(table_name)")! // change server url accordingly
let jsonData = try? JSONSerialization.data(withJSONObject: json)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue( "Bearer \(token)", forHTTPHeaderField: "Authorization")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON) //Code after Successfull POST Request
}
}
task.resume()
}
From your code, request body seems to be made like:
{"Person Name":"Rabiit Con","Food Type":"Minseee"}
What it needs to be sending is:
"fields": {
"Person Name":"Rabiit Con",
"Food Type":"Minseee"
}
Try
let json: [String: Any] = ["fields": ["Food Type": "Minseee",
"Person Name": "Rabiit Con"]]
let jsonData = try? JSONSerialization.data(withJSONObject: json)

Posting a String array to an API via JSON body in Swift

I am trying to upload a string array to the Edamam API that uses the data from my local database. For the API, I need to post an array of strings with a label "ingr" so that it would recognize it. I should be able to enter the "\(mass) grams \(name)" of each ingredient and get a response that would analyze the macronutrients of said ingredient. The code I'm using:
API Config:
func getData(strURL: String, dictParam: Dictionary<String, Any>, completion: #escaping(Dictionary<String, AnyObject>)->()) {
var request = URLRequest(url: URL(string: strURL)!)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: dictParam, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
print(response!)
do {
let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, AnyObject>
print(json)
completion(json)
} catch {
print("error")
}
})
task.resume()
}
API call:
let dictParams = ["ingr":["100 grams apple"]] as Dictionary<String, Any>
APICalling.shared.getData(strURL: baseURL, dictParam: dictParams) { (response) in
action()
}
}
When using the Rested app, I can upload as many ingredients as I want and will get the correctly formatted response, everything is dandy. However, when I try to implement the code in my app, it prints "error":conflict. Any ideas how I can properly implement the API call?
Found a fix to the issue. Added some headers to my request, everything works fine now.
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("*/*", forHTTPHeaderField: "Accept")
request.addValue("no-cache", forHTTPHeaderField: "Cache-Control")
request.addValue("api.edamam.com", forHTTPHeaderField: "Host")
request.addValue("gzip, deflate", forHTTPHeaderField: "Accept-Encoding")
request.addValue("keep-alive", forHTTPHeaderField: "Connection")

Http POST request in swift to send an email via Mailjet

I'm trying to send an email with the Mailjet API v3 with a http post request but I'm getting an error 400.
I used the exact same body with success in Javascript, but I guess the error 400 is related with it...
Any ideas ?
var recipients = [Any]()
recipients.append(["Email": "email#gmail.com"])
var body: [String: Any] = [
"FromEmail": "anEmail#gmail.com",
"FromName": "Me",
"Subject": "YEEES",
"Text-part": "Greetings from IOS ;)",
"Recipients": recipients
]
var request = URLRequest(url: self.apiURL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Authorization", forHTTPHeaderField: "Basic <keysInBase64>")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: body, options: [])
}
catch {
print("error during JSON serialization")
dump(error)
return
}
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
print(error)
print(response)
print(data)
})
task.resume()
Headers was wrong...
I was doing :
request.setValue("Authorization", forHTTPHeaderField: "Basic <keysInBase64>")
Instead of :
request.setValue("Basic <keysInBase64>", forHTTPHeaderField: "Authorization")
Using the Charles Proxy as suggested by #LouFranco, I was able to find the mistake.

Swift 2.0 POST Body null

Using a packet analyzer, I'm getting that my HTTP body is null. Is there any reason why my params aren't getting sent in the POST request?
let request = NSMutableURLRequest(URL: NSURL(string:"SERVERURL")!)
request.HTTPMethod = "POST"
do {
let params = ["returnInt":"5"] as Dictionary<String,String>
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
} catch {
//Do nothing
}
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
if error != nil{
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("\(responseString)")
}
task!.resume()
As I saw with println() in the Playground, the request.HTTPBody is not nil. Also, my analyzer shows not nil either:

HTTP Request with Body using PATCH in Swift

I'm trying to send a Patch request with a serialized JSON Body.
For some reason the server is not able to receive the body properly. I have a feeling that there seems to be a problem with the PATCH method in combination with the http request body.
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
var URL = B2MFetcher.urlForBooking(event.unique, bookingID: booking.unique)
let request = NSMutableURLRequest(URL: URL)
request.HTTPMethod = "PATCH"
// Headers
println(token)
request.addValue(token, forHTTPHeaderField: "Authorization")
request.addValue("gzip, identity", forHTTPHeaderField: "Accept-Encoding")
// JSON Body
let bodyObject = [
"op": "cancel"
]
var jsonError: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(bodyObject, options: nil, error: &jsonError)
/* Start a new Task */
let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response : NSURLResponse!, error : NSError!) -> Void in
completion(data: data, response:response , error: error)
})
task.resume()
You could try to add a Content-Type header to the request:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
or use one of the other JSON Content-Type formats described here.
I tested it with an ExpressJS server and without the Content-Type header the server got an empty body, but with a Content-Type header it worked well.
in swift 3/4 :
let request = NSMutableURLRequest(url: NSURL(string: "http://XXX/xx/xxx/xx")! as URL)
request.httpMethod = "PATCH"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do{
let json: [String: Any] = ["status": "test"]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
request.httpBody = jsonData
print("jsonData: ", String(data: request.httpBody!, encoding: .utf8) ?? "no body data")
} catch {
print("ERROR")
}
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
completion(false)
return
}
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
completion(true)
return
}
task.resume()
Simple Way to use patch without using HTTPBody
If you want to just use patch, you just need to change the value of the name of a specific user then it will be like:
let myurl = URL(string: "https://gorest.co.in/public-api/users/"+"\(id)?"+"name=abc")!
var request = URLRequest(url:myurl)
request.addValue("Bearer yourAuthorizationToken",forHTTPHeaderField:"Authorization")
request.httpMethod = "PATCH"
let dataTask = URLSession.shared.dataTask(with: request)
dataTask.resume()
Note: here "id" will be userId

Resources