Sending JSON POST request in Swift3 - ios

In my app i'm trying to make http post request with json data. The following json must be transferred to api
{
"Password":"123456",
"Email":"test#gmail.com"
}
Here is my code for this task
let dict = ["Email": "test#gmail.com", "Password":"123456"] as [String: Any]
if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: []) {
let url = NSURL(string: "http://xxxxxxxxx.net/api/Login")!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
if error != nil{
print(error?.localizedDescription)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let resultValue:String = parseJSON["success"] as! String;
print("result: \(resultValue)")
print(parseJSON)
}
} catch let error as NSError {
print(error)
}
}
task.resume()
}
I'm getting the following error
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}
The response data is empty. What I'm doing wrong, or i have missed something in my code?

Try two things:
First :
jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
then add logs if your data is converted into JSON. Convert your data into String and print the value.
Also add
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
before httpBody. Sometimes we have to tell server in our request that we are posting JSON data.
Hope this will help you!!
Happy Coding!

Related

Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 1." UserInfo={NSDebugDescription=Invalid value around character 1. swift 4

I got response from api via postman
{
"status": "1",
"error": false,
"message": "Your order has been placed successfully"
}
I called api and pass the params which required to call api. The code is giving an error "Invalid value around character 1."
let urlsContainer = UrlsContainer()
let url = URL(string: urlsContainer.allotRunnerAPI)
let session = URLSession.shared
var request = URLRequest(url: url!)
let postString = "user_id=\(user_id)&pincode=\(pincode)&select_address=\(select_address)&store_id=\(store_id)"
request.httpMethod = "POST"
request.httpBody = postString.data(using: .utf8)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
The code should execute the do block of code
do {
let parsedData = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: AnyObject]
print(parsedData)
}
but now because of some problem in code it is executing catch block of code
catch let error {
print(error)
}
})
task.resume()
I am not able to find the problem in my code to resolve the error
use [String:String] to send data to api
let params = ["user_id":user_id,
"pincode":pincode,"select_address":select_address,
"store_id":store_id]
let data = JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
post this data as your body

How to resolve issue? I given description in body

// Hi, i got response from url but getting error as below in title, please fix the issue.
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0
let Url = String(format: "http://www.fgndbdsn.in/index.php?route=api/mywebservices/addition")
guard let serviceUrl = URL(string: Url) else { return }
let parameterDictionary = ["first" : "25", "second" : "25"]
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: []) else {
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [[String:Any]]
print(json)
}catch {
print(error)
}
}
}.resume()
The response from the server must be valid JSON with a top level container which is an array or dictionary.

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

Mysterious Network issues with posts. Wifi Works, Cell doesn't

I keep getting a timeout with sending post requests when my actual device is on 3G or 4G. However, when I'm on wifi, the post request is immediately received on the server side.
Here's my code that involves the post request. I'm getting a Optional("The request timed out."). I don't think the session length should be a problem since it times out after a long time and the data that is being sent is just a username with a password. Any thoughts?
I run a flask server, but I don't think it's relevant so I didn't include its code.
if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) {
let url = NSURL(string: base_address + taglocation_address)!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
print("starting task")
let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
if error != nil{
self.statusLabel.text = error?.localizedDescription
print(error?.localizedDescription)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as? NSDictionary
print("doing something")
if let responseJSON = json as? [String: String] {
print(responseJSON)
self.statusLabel.text = responseJSON["status"]
}
} catch let error as NSError {
self.statusLabel.text = error.localizedDescription
print(error)
}
}
task.resume()
}
In your NSMutableURLRequest object, try adding allowsCellularAccess property and set it to true. Refer to my code below.
if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) {
let url = NSURL(string: base_address + taglocation_address)!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
request.allowsCellularAccess=true //Add this line
print("starting task")
let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
if error != nil{
self.statusLabel.text = error?.localizedDescription
print(error?.localizedDescription)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as? NSDictionary
print("doing something")
if let responseJSON = json as? [String: String] {
print(responseJSON)
self.statusLabel.text = responseJSON["status"]
}
} catch let error as NSError {
self.statusLabel.text = error.localizedDescription
print(error)
}
}
task.resume()
}

iOS create JSON file as sample data to test network and parsing logic

I'm working with an project dealing with send request to server and get JSON response. Is there a way to create a offline JSON file as sample data so that the app read from sample data file instead of making real network request? I want to test the JSON parsing and mapping before write network call
For example, how can we make a JSON file from this JSON?
{
"by" : "dhouston",
"descendants" : 71,
"id" : 8863,
"kids" : [ 8952, 9224, 8917, 8884, 8887, 8943, 8869, 8958, 9005, 9671, 9067, 8940, 8908, 9055, 8865, 8881, 8872, 8873, 8955, 10403, 8903, 8928, 9125, 8998, 8901, 8902, 8907, 8894, 8878, 8980, 8870, 8934, 8876 ],
"score" : 111,
"time" : 1175714200,
"title" : "My YC app: Dropbox - Throw away your USB drive",
"type" : "story",
"url" : "http://www.getdropbox.com/u/2/screencast.html"
}
use this to serialize, post and get a json back:
let json = ["by":"dhouston","descendants":"71"]
do {
let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
let url = NSURL(string: "your url")!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
request.httpBody = jsonData
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
if error != nil{
print(error!.localizedDescription)
return
}
let header = response as! HTTPURLResponse
print(header.allHeaderFields)
do {
let responseObject = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String: String] // your json response for example [String: String], depends on what you get as a response
print(responseObject)
// do something
} catch let jsonError {
print(jsonError)
print(String(data: data!, encoding: String.Encoding.utf8)!)
}
}
task.resume()
} catch {
print(error)
}
if you just want to serialize use:
let json = ["by":"dhouston","descendants":"71"]
do {
let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
} catch {
print(error)
}
Save your json file in your main bundle, then you can read it as json data, followed by parsing:
let filePath = Bundle.main.path(forResource: "jsonfile", ofType: "json")
let data = Data(contentsOf: URL(string: filePath)!)
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
} catch error {
print(error)
}
Create new file with Strings by Xcode->New->File->String File
Rename file with File.json
Use below code SWIFT 3.x for picking .json file
override func viewDidLoad() {
super.viewDidLoad()
let sampleDataPath = Bundle.main.bundleURL.appendingPathComponent("File.json").path
print(sampleDataPath)
}

Resources