Encoding JSON body properly in Swift for HTTP Request - json

I am trying to encode key/value pairs in JSON for an HTTP request in Swift on iOS 15, but everything I try to put in the body shows up as the key when I post it.
The code:
var request = URLRequest(url: url)
let body = [
"email": "abc#gmail.com",
"password": "123456"
]
let bodyData = try? JSONSerialization.data(
withJSONObject: body, options: []
)
request.httpMethod = "POST"
request.httpBody = bodyData
When I post this to the server, the server receives:
{
"{\"email\":\"abc#gmail.com\",\"password\":\"123456\"}": ""
}
Am a Swift beginner, many thanks for any responses to this...

Try adding this to the request
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
That is what solved it for me when I had the same problem. This tells the server to parse the json as json instead of
{ jsonBody : "" }
which is what it seems to be doing right now.

Related

Swift trouble send request with dynamic field json

I've got simple struct:
struct LoginModel: Codable {
var user: String
var password: String
}
Fill my model and encode using JSONEncoder().
Next create URLRequest
let request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: timeOut)
let headers = [
"Content-Type": "application/json",
"cache-control": "no-cache",
]
request.allHTTPHeaderFields = headers
request.httpMethod = "POST"
request.httpBody = data
run URLSessionDataTask with this request from URLSession.shared.
Beckend gets json with null fields.
But instead I've sent dictionary with fixed filed it's work fine.
let parameters = [
"user": "user",
"password": "hash"
]
let data = JSONSerialization.data(withJSONObject: parameters, options: [])
When I decode using JSONDecoder() back to my model, all variable are filled.
Server side endpoints using other apps written in objc. This app using NSDicionary and NSJSONSerialization and work fine.
How to pass JSON data dynamically.

How to send multiple JSON objects as a stream using alamofire

I want to send multiple different JSON object in a single request, i felt streaming the multiple JSON objects like a file in a single request would be better, so kindly let me know if it is possible, if so kindly give me an idea of how to do it using Alamofire, Below is the formate of the raw body (application/json) data that i want to post
{"a":23214,"b":54674,"c":"aa12234","d":4634}
{"a":32214,"b":324674,"c":"as344234","d":23434}
{"a":567214,"b":89674,"c":"sdf54234","d"34634}
I tried the below code, but it didn't work as the body param is not in the correct format, that's the reason i want to try sending the multiple JSON objects as a stream in a single request, Kindly advice
let SendParams = [
["a":1234, "b":2345, "c":3456], ["a":2345, "b":3456, "c":4567], ["a":3456, "b":4567, "c":5678]
]
_ = Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding, headers: header)
JSON format is not correct for your request, JSON is always key-value pair, where key is always String, and value is any Object. In your example need to set key at top level for object of type Array as below:
let SendParams = [
"key" :[["a":1234, "b":2345, "c":3456], ["a":2345, "b":3456, "c":4567], ["a":3456, "b":4567, "c":5678]]
]
_ = Alamofire.request(url, method: .post, parameters: SendParams, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in}
OR
Serialise the array and set as httpBody of URLRequest object:
let url = YOUR_POST_API_URL
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let values = [
["a":1234, "b":2345, "c":3456], ["a":2345, "b":3456, "c":4567], ["a":3456, "b":4567, "c":5678]
]
request.httpBody = try! JSONSerialization.data(withJSONObject: values)
Alamofire.request(request)
.responseJSON { response in
// do whatever you want here
switch response.result {
case .failure(let error):
print(error)
if let data = response.data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
case .success(let responseObject):
print(responseObject)
}
}

Sending (POST) Json Array with Alamofire

I am trying to send an array of JSON-Objects to my server using Alamofire.
As postparameters only Dictionary<String, AnyObject> are allowed in Alamofire. So I tried to do it with an NSMutableURLRequest.
But it doesn't work, too. I am using SwiftyJSON, too.
This is what I trying, but I cant put the Array in the Body.
//testClassList: [TestClass]
let uri : String = serveraddress + "/SendClassList";
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: uri)!)
mutableURLRequest.HTTPMethod = "POST"
var header : [String:String] = createHeader();
mutableURLRequest.addValue(header["Authorization"]!, forHTTPHeaderField: "Authorization");
mutableURLRequest.addValue(header["Content-Type"]!, forHTTPHeaderField: "Content-Type");
mutableURLRequest.addValue(header["Accept"]!, forHTTPHeaderField: "Accept");
do{
mutableURLRequest.HTTPBody = JSON(testClassList);
}catch{
print(error)
}
Alamofire.request(mutableURLRequest).responseJSON { response in
if(response.response?.statusCode == 200){
let resp: String = response.result.value as! String;
completionHandler?(resp, nil);
}
}
Is there a way to post an Array direct without wrapping it into another JSON like ["list":testClassList]
(Please only Swift 2.+ Code.)
best regards

Parameters in JSON POST Request ignored in Swift?

I am trying to get some data from a URL which requires me to POST a JSON request. It works in the sense that I get some data back; just not the data I expected. I then used jsontest.com to test my code:
let url = NSURL(string: "http://echo.jsontest.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
do {
let params = ["echo": "abc"] as Dictionary<String, String>
//... Just make sure that 'params' is a valid JSON object
assert(NSJSONSerialization.isValidJSONObject(params))
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
} catch {
print("Error")
}
let session = NSURLSession.sharedSession()
dataTask = session.dataTaskWithRequest(request, completionHandler: {
(data: NSData?, response: NSURLResponse?, error: NSError?) in
if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200,
let data = data {
let encodedData = NSString(data:data, encoding:NSUTF8StringEncoding)
print("encodedData = \(encodedData!)")
} else {
print("Error")
}
})
dataTask?.resume()
When I run this, I see the following output from jsontest.com:
encodedData = {"": ""}
where I expected
encodedData = {"echo": "abc"}
So, do I not understand correctly whether this is how jsontest.com works, or am I doing something wrong? (Obviously, I had similar problems using other JSON services.) Any comments are appreciated.
echo.jsontest.com doesn't work with a request body but with a request url, see www.jsontest.com/#echo for details.
Turns out #Eric D is right. I found another website to test my JSON posts on and that one worked fine. So the code is basically correct after all.
I made the following changes:
let url = NSURL(string: "http://gurujsonrpc.appspot.com/guru")
let params = [ "method" : "guru.test", "params" : [ "GB" ], "id" : 123 ] as Dictionary<String, AnyObject>
and then I get the following response:
{"jsonrpc":"2.0","id":123,"result":"Hello GB!"}
Which is exactly what was expected.
Thanks!
The correct URL is http://validate.jsontest.com
Also, I don't think you are constructing the POST request body correctly. See How are parameters sent in an HTTP POST request?

How to create a particular data structure in swift . Swifty Json not useful :(

i'm porting my really simple app from javascript (embedded in an app) to ios8/swift and Xcode.
The app will insert some simple event in google calendar using CalendarApiV3.
In javascript it was easy to create a simple data structure to pass in a http POST request, like this structure :
var data:struct =
{
"end": {
"dateTime": "20141223T12:25:00Z"
},
"start": {
"dateTime": "20141223T10:25:00Z"
},
"summary": "description of event",
"reminders": {
"useDefault": false,
"overrides": [
{
"method": "sms",
"minutes": "60"
},
{
"method": "email",
"minutes": "60"
}
]
}
};
Ok, how to re-create the some structure in Swift ?
I ended up looking for swifty json, but they all tell me how to PARSE json requested, not how to FORM a json request.
I hope i was clear.
Thanks in advance.
Victor
Here's a very simple example and I assume that nobody wants to deal with JSON strings, they want to have them created from data structures.
var dict1 = ["dave": "drangle", "hume": "cronyn"]
var dict2 = ["bob": "fossil", "vince": "powers"]
var ary = [dict1, dict2]
var jsonData = JSON(ary)
var post:NSData = jsonData.rawData()!;
var postLength:NSString = String(post.length)
var url:NSURL = NSURL(string: "https://some.server.com/mobile.php")!
var request:NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = post
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
if let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil) {
println(data)
}
As you can see, it's an array of dictionaries which then gets converted to a SwiftyJSON struct. The jsonData.rawData()! is what gets you NSData which is the required datatype for request.HTTPBody. Here's what you see on the PHP server side of things using file_get_contents("php://input") and print_r(json_decode()):
[{"hume":"cronyn","dave":"drangle"},{"bob":"fossil","vince":"powers"}]
Array
(
[0] => stdClass Object
(
[hume] => cronyn
[dave] => dangler
)
[1] => stdClass Object
(
[bob] => fossil
[vince] => powers
)
)
SwiftyJSON is great for building JSON object from AnyObject in swift.
You can take a look at the site about how to create JSON object from AnyObject.
After you have your own JSON object, the site actually mentioned about how to creating JSON string you can use in HTTP Request.
if let string = json.rawString() {
//Do HTTP Request here
}
here cezar answered greatly about how to use HTTP Request in swift : How to make an HTTP request in Swift?
Update:
So I assume that you have jsonString available, you can use this to make your swiftyJSON object
let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let jsonObject = JSON(data: data!)