Sending JSON data in the body of an Alamofire Request - swift3

I'm trying to make an api call to submit some data using Alamofire (version 4.0). The trouble i'm having is that when making the call I get a response from the server that the JSON data was not in a valid format.
Is there a way to check if the data data is being serialized correctly in Alamofire?
I have tried many of the solutions currently on StackOverflow and cannot find a solution. Thanks for your help.
This should be the format of the request body:
{
"reference_id": "Test001",
"data": {
"type": "step",
"data": {
"2015-08-02": 8574
}
}
}
My Swift code:
let params: [String:Any] = [
"reference_id": "someName",
"data": [
"type" : "step",
"data": [
"2015-08-02": 8574
]
]
]
print(params)
if let userToken = userToken {
let request = Alamofire.request(url+"API.php?Action=SaveHealthData", method: .post, parameters: params, encoding: JSONEncoding.default).responseString(completionHandler: { response in
print(response)
})
}
The error I'm getting is:
Warning: json_decode() expects parameter 1 to be string, array given in /var/www/html/API/SaveHealthData.php on line 8
{"error":"data not in valid json format"}

Here is the solutions of your problem,
var dataDict : [String : Any] = [:];
dataDict["type"] = "Step"
dataDict["data"] = ["2015-08-02": 8574];
let params: [String:Any] = ["reference_id": "someName",
"data": String.toJSonString(data: dataDict)];
Here toJSonString is an extension of String
static func toJSonString(data : Any) -> String {
var jsonString = "";
do {
let jsonData = try JSONSerialization.data(withJSONObject: data, options: .prettyPrinted)
jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String
} catch {
print(error.localizedDescription)
}
return jsonString;
}
Happy Coding

Related

postman: save response on a global variable

With PostMan, how can save the follow response:
[
{
"id": "6254c754-5a97-43fd-9b48-c428b9bd69e5",
"name": "fdsfds",
"description": "fdzf",
"type": 0,
"createDate": "2018-08-01T17:49:29.071+01:00",
"lastUpdateDate": "2018-08-01T17:49:29.071+01:00",
"lastUpdateUser": null,
"variables": null,
"instructions": null
}
]
on a variable? For example the id?
var jsonData = pm.response.json();
console.log(jsonData.id);
pm.globals.set("variable_key", jsonData.id);
to set the environment variable "authkey" from response
var obj = pm.response.json()["token"];
pm.environment.set("authkey", obj);
You can't save JS Objects directly in a global variable but you can use JSON library to convert your object to string and save, like the following code:
// create the JS Object
var obj = {
foo: "bar",
some_number: 91
}
// convert the obj to string and save in the globals
pm.globals.set("my_obj", JSON.stringify(obj));
// get obj from globals and parse to JS Object again
var obj_from_globals = JSON.parse(pm.globals.get("my_obj"));
// print int he console
console.log(obj_from_globals);
You should expect this in your console:
I think i resolve this with:
var jsonData = pm.response.json();
for (var key in jsonData) {
if (jsonData.hasOwnProperty(key)) {
var seqDelete = jsonData[key].id;
console.log(seqDelete);
}
}
pm.globals.set("seqDelete", seqDelete);
This isn´t totally correct.
If i have multidimension array, this only gets one ID value
This is the response that I work with:
{id: "myId", version: "2.0", name: "test"…}
This is how I set the id value from the response into my global variable "appId":
var requestJson = JSON.parse(request.data);
console.log(requestJson)
postman.setGlobalVariable("appId", requestJson.id);
Result:

Alamofire AFError invalidURL

Im not able to find where i have gone wrong.I tried all possible solutions but nothing seems to work.
Can anyone suggest where I have gone wrong?
My code is as below:
var diaryEntryUrl = "http://myUrl?uid=10001&diary_text=\(textPrint)&location=\(loactionAddrEnc)"
// var diaryEntryUrl = diaryEntryUrlEncode.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) --- tried encoding, but didn't work
let postParameters:[String: Any] = [ "imagesName": self.awsImageArray2, "tagsList": self.tagArray]
Alamofire.request(diaryEntryUrl, method: .post, parameters: postParameters, encoding: JSONEncoding.default, headers: [:]).responseJSON {
response in
if response.result.isSuccess{
print("SuccessFully Added")
}else{
print("Error \(String(describing: response.result.error))")
}
}
I tried encoding the texts also but still error is there.I did it as below:
loactionAddrEnc = loactionAddr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
var textPrint = diaryEntryText.text.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
I am getting the follwing error:
As you can see in the log Optional for location and diary text. So it means you need to unwrap it first.
if let textPrint = textPrint, let loactionAddrEnc = loactionAddrEnc {
var diaryEntryUrl = "http://myUrl?uid=10001&diary_text=\(textPrint)&location=\(loactionAddrEnc)"
// rest of your code
}
This should solve your problem. But there is another way.
You can pass all your query params in postParameters.
var diaryEntryUrl = "http://myUrl"
var postParameters:[String: Any] = [ "imagesName": self.awsImageArray2, "tagsList": self.tagArray]
postParameters["uid"] = "10001"
if let textPrint = textPrint {
postParameters["diary_text"] = textPrint
}
if let loactionAddrEnc = loactionAddrEnc {
postParameters["location"] = loactionAddrEnc
}
Alamofire.request(diaryEntryUrl, method: .post, parameters: postParameters, encoding: JSONEncoding.default, headers: [:]).responseJSON {
response in
if response.result.isSuccess {
print("SuccessFully Added")
}else{
print("Error \(String(describing: response.result.error))")
}

Parsing data returned from server using Alamofire and SwiftyJSON, what is the data type returned?

I hope I manage to ask this properly:
I am using Alamofire and SwiftyJSON for managing the JSON files I get from the server.
I have issues with understanding the type of response.result.value , how to cast it to an object I can construct it with SwiftyJSON's JSON(data: data) constructor.
This is my code for the request using Alamofire:
func performRequest() {
// parameters["retry_count"] = retryNum
if let _ = host, let path = path {
let request = Alamofire.request(HOST + path, method: method, parameters: parameters, headers: headers)
request.responseJSON { response in
print("-----")
print(response.response?.statusCode)
print("-----")
// check if responseJSON already has an error
// e.g., no network connection
if let json = response.result.value {
print("--------")
print(json)
print("--------")
}
guard response.result.error == nil else {
print(response.result.error?.localizedDescription ?? "Response Error")
self.completionHandler?(response.result.isSuccess, nil)
self.retryRequest()
return
}
// make sure we got JSON and it's a dictionary
guard let json = response.result.value as? [String: AnyObject] else {
print("didn't get dictionary object as JSON from API")
self.completionHandler?(response.result.isSuccess, nil)
self.retryRequest()
return
}
// make sure status code is 200
guard response.response?.statusCode == 200 else {
// handle status code
self.completionHandler?(response.result.isSuccess, nil)
return
}
self.completionHandler?(response.result.isSuccess, json)
RequestsQueue.sharedInstance.sema.signal()
}
}
This results with this print:
{
numOfShiftsInDay = 3;
shifts = (
{
endTime = "14:00";
startTime = "07:30";
},
{
endTime = "20:00";
startTime = "13:30";
},
{
endTime = "02:00";
startTime = "19:30";
}
);
}
this data type is a [String: AnyObject].
I want to use it to construct a SwiftyJSON JSON object since it is easier for me to parse the data using SwiftyJSON methods..
This is the code I try for parsing it and then using it but obviously it doesn't work:
let json = JSON(data: data)
I get this compilation error:
Cannot convert value of type '[String : AnyObject]?' to expected argument type 'Data'
So how should I go about this?
You need to use JSON(data) instead of JSON(data: data) because this init(data:) wants Data as argument.
Changed line
let json = JSON(data: data)
To
let json = JSON(data)

Migration Alamofire swift2 from swift 3

Previously in my APP when I was making a call to the server if there were any errors I did the following:
Alamofire.request(mutableURLRequest).responseJSON{
response in if let JSON = response.result.value{
if JSON.count != 0{
let errorList = JSON["responseErrorsList"] as? NSArray
for error in errorList!{
let erro: String = error as! String
switch erro{
case "PersonRequired":
With the migration from swift 2 to swift 4 I am having problems because theList errors comes to nil however the result of JSON is as follows:
["Rate": , "Level": , "Code": , "ID": 0, "Zone": , "Address": , "ErrorsListServer": <__NSSingleObjectArrayI 0x17400ba90>( InvalidCode ) , "SubZone": ]
Does anyone know how I can access the "ErrorsListServer" field and fetch the errors that in this case is "InvalidCode".
What I have implemented and is not working for is the following:
if let JSON = response.result.value as? [String: Any]{
if (JSON as AnyObject).count != 0{
let errorList = JSON["responseErrorsList"] as? [[String: Any]]
From your JSON response, you need to access key ErrorsListServer and it is Array of String not Array of Dictionary so you need to cast it to [String]. Also you can reduce your code with single if let statement like this way.
if let JSON = response.result.value as? [String: Any],
let errorList = JSON["ErrorsListServer"] as? [String] {
for error in errorList {
print(error)
}
}

Swift 3.0 Alamofire 4.0 - Domain=NSURLErrorDomain Code=-999 "cancelled"

I am trying to use Alamofire (latest version) with Swift 3.0, iOS 10 and xCode 8. Currently trying to do a post call. The code is written below and I keep getting the same issue. Please help, would appreciate anything on this.
private class func getDefaultHeaders() -> HTTPHeaders {
let headers: HTTPHeaders = [
"Connection" : "keep-alive",
"token" : "0781d3957fd8da6ee35c4e3124d974a2999925274771234",
"nonce" : "9b2436331ed908bb2f399568d2adbc4e",
"uuid" : "uuid",
"latitude" : "43.656781",
"longitude" : "-79.380823",
"Content-Type" : "application/json",
"userTypeId" : "1",
"userAgent" : "UserAgent",
"Content-Length" : "0",
"Host" : "localhost:8080",
"User-Agent" : "iOS Example/1.0 (com.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0"
]
return headers
}
func generateCustomSession() -> SessionManager {
let headers = ServicesController.getDefaultHeaders()
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = headers
let manager: SessionManager = SessionManager(configuration: configuration)
return manager
}
func post(url: String, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void) {
generateCustomSession().request(
url,
method: .post,
encoding: JSONEncoding.default)
.validate(statusCode: 200..<300)
.downloadProgress { (progress) -> Void in
print("download progress: \(progress.fractionCompleted)")
}
.responseJSON { (response) -> Void in
if #available(iOS 10.0, *) {
print(response.metrics)
}
debugPrint(response)
if response.result.isSuccess {
let resJson = JSON(response.result.value!)
success(resJson)
}
if response.result.isFailure {
let error : Error = response.result.error!
failure(error)
}
}
}
"cancelled" may happen if there is a problem with a suspicious https certificate that could be fixed by the user allowing access, and that doesn't happen.
Quite possible the root cause is the server using a less than perfect certificate.
I found a way to resolve the issue. Below is code that will help you cancel authentication challenge. I don't recommend this, this useful for temporary solution. The best thing to do is still validate the authentication challenge fully.
let manager: SessionManager = SessionManager(configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: URLSession.AuthChallengeDisposition = .cancelAuthenticationChallenge
var credential: URLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = URLSession.AuthChallengeDisposition.useCredential
credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
} else {
if challenge.previousFailureCount > 0 {
disposition = .cancelAuthenticationChallenge
} else {
credential = manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)
if credential != nil {
disposition = .useCredential
}
}
}
return (disposition, credential)
}
return manager
}