Alamofire doesnt allow to send object directly - ios

My API only accepts object as the body , but alamofire only sends Dictionary as an object, which my server is not accepting requesting help
I have to call an API which is a post api using alamofire
as soon as i convert the model to dictionary and dicitionary to json
and post it Alamofire does not allow me to post a string
it allows me to send a dictionary which my api does not accept
["key":"value"]- Not acceptable
{"key":"value"}- Acceptable
Can anyone share any solution?
I am using Swift 5 , Xcode 10, Alamofire 4.8.2
do{
let d = try data.asDictionary()
jsonString = DictionaryToJSON(data: dictionary)
} catch {
print(error)
}
Alamofire.request(url, method: .post, parameters: jsonString, encoding: .utf8, headers: [: ]).responseJSON { (res) in
print(res.result)
print("Request Data \(res.request) \n Dictionary \(jsonString)")
do {
let d = try JSONDecoder().decode([OTPMessage].self, from: res.data!)
print(d[0].message)
} catch {
print(error)
}
}
// Dictionary to JSON
func DictionaryToJSON(data: [String:Any])->String {
if let theJSONData = try? JSONSerialization.data(
withJSONObject: data,
options: .prettyPrinted
),
let theJSONText = String(data: theJSONData, encoding: String.Encoding.ascii) {
print("JSON string = \n\(theJSONText)")
return theJSONText
}
else {
return ""
}
}
// Object to Dictionary
extension Encodable {
func asDictionary() throws -> [String: Any] {
let data = try JSONEncoder().encode(self)
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
throw NSError()
}
return dictionary
}
}
//Struct
struct OTPMessage:Codable {
var message = String()
}

You don't have to convert your dictionary to a JSON String because Alamofire can do the encoding, see this example.
I suggest you to change your code to something like this
do{
let dictionary = try data.asDictionary()
Alamofire.request(url, method: .post, parameters: dictionary, encoding: .JSON, headers: [:]).responseJSON { (res) in
print(res.result)
print("Request Data \(res.request) \n Dictionary \(jsonString)")
do{
let d = try JSONDecoder().decode([OTPMessage].self, from: res.data!)
print(d[0].message)
}catch{
print(error)
}
}
} catch{
print(error)
}

With Alamofire you can not do this. What you need to do is creating a URLRequest object and setting the httpBody property of it and then passing it to Alamofire.
URLRequest allows you to have Data as POST body.
var request = URLRequest(url: urlFinal)
request.httpMethod = HTTPMethod.post.rawValue
request.allHTTPHeaderFields = dictHeader
request.timeoutInterval = 10
request.httpBody = newPassword.data(using: String.Encoding.utf8)
Alamofire.request(request).responseString { (response) in
if response.response!.statusCode >= 200 && response.response!.statusCode <= 300 {
completion("success")
}else {
completion("failed")
}
}
here newPassword is string. from there I created the Data object. You have to convert your Custom class object to Data object.

Related

Issue while sending array of dictionary in swift

I am creating array of dictionaries and then passing that in paramDictionary and sending to server but I get responseStatus code 422. I am using Alamofire 5.
Here is the structure of param which I have to send and it successfully working on postman but in app it is always fails
{"check_in": [{"check_in_at":"2020-02-26 03:23:44", "gps_coordinates":"3.1697998046875,101.61672197976593"},
{"check_in_at":"2020-02-26 03:23:45","gps_coordinates":"3.1697998046875,101.61672197976593"}]}
Here is my code
func postCheckInApi(viewController: UIViewController,
completion:#escaping (_ result:SuccessErrorData)->(),
errorHandler:#escaping (_ result:Error,_ statusCode:Int?)->()//error handler
) {
let url = KCheckin
let geoArr = Constant.getSearchLocationHistory() ?? [GeoTaggingEntity]()
var arr = [[String: String]]()
for i in geoArr{
let dict: [String : String] = ["gps_coordinates" : i.gps_coordinates ?? "", "check_in_at" : i.check_in_at]
arr.append(dict)
}
let parameterDictionary = ["check_in": arr] as [String : Any]
print(parameterDictionary)
let headers: HTTPHeaders = [
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": Constant.getBearerToken() ?? ""
]
AF.request(url, method: .post, parameters: parameterDictionary, headers: headers).responseData { response in
switch response.result{
case.success(let data):
do{
let jsonData = try JSONDecoder().decode(SuccessErrorData.self, from: data)
print("Success")
completion(jsonData)
}
catch{
//viewController.navigationController?.popToRootViewController(animated: true)
}
case .failure(let error):
print(error)
}
}
}
You can not add Array as parameter object to your paramDictionary. You need to covert your Array to json string and then add it to you paramDictionary.
For that use below Collection extension to convert your Array to Json String
extension Collection {
func json() -> String? {
guard let data = try? JSONSerialization.data(withJSONObject: self, options: []) else {
return nil
}
return String(data: data, encoding: String.Encoding.utf8)
}
}
How To Use
let jsonStr = yourArray.json()
add this jsonStr to your paramDictionary

How to send single quotes in a array as parameter , As i am calling a api using alamofire?

I have to call a api to get a functionality done. In that I have to send a array as a parameter which consists single quotes. But i tried adding a single quote in that , but i am failing miserably getting nil value.
I tried removing the backslash which automatically gets created while trying to send single quotes.
{
"buyerId":"ananth",
"state":"California",
"mobile_no":"5896235966",
"permissionType":"3",
"communityNoArray":"['1441','1643']",
"community_name":"abrakasdabrama"
}
// try this
{
"buyerId":"ananth",
"state":"California",
"mobile_no":"5896235966",
"permissionType":"3",
"communityNoArray":["'12'","'123'"],
"community_name":"abrakasdabrama"
}
Maybe you should create a string from your JSON object. Try with this code:
func jsonToString(json: AnyObject) -> String{
do {
let data1 = try JSONSerialization.data(withJSONObject: json, options: JSONSerialization.WritingOptions.prettyPrinted)
let convertedString = String(data: data1, encoding: String.Encoding.utf8)
return convertedString!
} catch let myJSONError {
print(myJSONError)
return ""
}
}
let jsonData = [
"buyerId":"ananth",
"state":"California",
"mobile_no": "5896235966",
"permissionType": "3",
"communityNoArray": "['1441','1643']",
"community_name": "abrakasdabrama",
] as [String : Any]
Then you can call it like
let messageString = jsonToString(json: jsonData as AnyObject)
After this, you can send it like a string.
You can convert your param in to Json string by using following method
func convertToJsonString(from object: Any) -> String? {
if let objectData = try? JSONSerialization.data(withJSONObject: object, options: JSONSerialization.WritingOptions(rawValue: 0)) {
let objectString = String(data: objectData, encoding: .utf8)
return objectString
}
return nil
}

How to parse json in swift (convert json string to string)

I don't find a way to parse a simple json object into a string object in swift. I have a network request which gives me this json response:
"\"asdf\""
When I try to parse this into a string in swift it looks like this:
"\"asdf\""
according this documentation from apple I should only need to do this:
Apple Swift documentation
let jsonValue = responseData as? String
But that does not work for me.
I need just asdf as string value.
Can anyone help me out?
Thanks in advance.
EDIT:
Here is my network request code:
let stringUrl = "https://test.fangkarte.de/v1.3/test"
let url = URL(string: stringUrl)!
let request = URLRequest(url: url)
let session = URLSession(configuration: URLSessionConfiguration.default)
let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in
if let data = data {
let json = String(data: data, encoding: String.Encoding.utf8)
let response = response as! HTTPURLResponse
if 200...299 ~= response.statusCode {
callback(true, response.statusCode, json!)
} else {
callback(false, response.statusCode, json!)
}
}
})
task.resume()
The value of the variable json is "\"testString\"" and not "testString"
You could try something like:
func parseJSON(_ data: Data) -> [String: Any]? {
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let body = json["data"] as? [String: Any] {
return body
}
} catch {
print("Error deserializing JSON: \n\(error)")
return nil
}
return nil
}
To use:
let data = <variable holding JSON>.data(using: .utf8)
let jsonResult = parseJSON(data)
You get a json string so you can try
let jsonstring = "\"asdf\""
let data = jsonstring.data(using: .utf8)
do {
if let str = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as? String {
print(str)
}
}
catch let caught as NSError
{
}

PATCH with Alamofire (swift 2.3)

I have a problem, i try to update with PATCH method using Alamofire, but no changes are reflected.
I Think in one of those I am making some mistake.
This is my code:
Alamofire.request(.PATCH, url, parameters: ["op": "replace", "path": "/IsVacinated", "value": true], encoding: .JSON)
.responseJSON { response in
Utils.endRequest(progressView)
if let data = response.data {
let json = JSON(data: data)
if json != nil {
self.navigationController?.popViewControllerAnimated(true)
print(json)
}
else {
print("nil json")
}
}
else {
print("nil data")
}
}
I hope you can help me, and that I have searched and not much information.
Best regards.
You need to use a custom encoding and send your parameters as a raw string in the body
let enconding: ParameterEncoding = .Custom({convertible, params in
let mutableRequest = convertible.URLRequest.copy() as? NSMutableURLRequest
mutableRequest?.HTTPBody = "[{\"op\" : \"replace\", \"path\" : \"/IsVacinated\", \"value\":true"}]".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
if let mutableRequest = mutableRequest {
return (mutableRequest, nil)
}
let error = NSError(domain: "Custom", code: -1, userInfo: nil)
return (convertible.URLRequest, error)
})
Finally using the custom encoding
Alamofire.request(.PATCH, url, parameters: [:], encoding: encoding)
.responseJSON { response in
Utils.endRequest(progressView)
if let data = response.data {
let json = JSON(data: data)
if json != nil {
self.navigationController?.popViewControllerAnimated(true)
print(json)
}
else {
print("nil json")
}
}
else {
print("nil data")
}
}
Swift 4 and Alamofire 4.6 example:
struct CustomPATCHEncoding: ParameterEncoding {
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
let mutableRequest = try! URLEncoding().encode(urlRequest, with: parameters) as? NSMutableURLRequest
do {
let jsonData = try JSONSerialization.data(withJSONObject: parameters!, options: .prettyPrinted)
mutableRequest?.httpBody = jsonData
} catch {
print(error.localizedDescription)
}
return mutableRequest! as URLRequest
}
}
func updateProfile() {
let phoneString = self.phone.value
let formattedPhoneString = phoneString.digits
var parameters : Parameters = ["email": self.email.value,
"first_name": self.firstName.value,
"last_name": self.lastName.value,
"id": self.id.value]
if formattedPhoneString.count > 0 {
parameters["phone"] = formattedPhoneString
}
Alamofire.request(APPURL.Profile,
method: .patch,
parameters: parameters,
encoding: CustomPATCHEncoding(),
headers:APIManager.headers())
.debugLog()
.responseJSON { response in
switch response.result {
case .success(let JSON):
print("Success with JSON: \(JSON)")
break
case .failure(let error):
print("Request failed with error: \(error.localizedDescription)")
break
}
}
}
Try using .PUT instead of .PATCH
The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; i.e., new resources may be created, or existing ones modified, by the application of a PATCH.
Also, Check is server receiving request from your app is correct or not. Check for URL, Parameters, format and call type. If all things is correct, check for response data.

JSON in NSData objects for common rest API

I'm trying to send data from my app to a rest API that is also being used by an Android app developed by another programmer. I have the JSON being converted into an NSData object using NSJSONSerialization.dataWithJSONObject and then attaching it to a NSURLRequest but the NSData object is a hexadecimal representation of the JSON String. According to the other developer his Android code is creating and transmitting the JSON object in UTF-8 encoding, so my question is how do I either send the JSON string as UTF-8 text or what is the best way to make the API able to handle both sources as seamlessly as possible?
EDIT: The code that I'm using now
func postToServer() {
let endPoint: String = "http://server.com"
guard let url = NSURL(string: endPoint) else {
print("ERROR: cannot create URL")
return
}
let urlRequest = NSMutableURLRequest(URL: url)
urlRequest.HTTPMethod = "POST"
urlRequest.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let loc = self.getLocation()
var content:[String: AnyObject] = ["action": "put-point", "request": ["rangeKey": self.id, "lng": loc.coordinate.longitude, "lat": loc.coordinate.latitude, "count": self.count]]
var data: NSData! = NSData()
do {
data = try NSJSONSerialization.dataWithJSONObject(content, options: NSJSONWritingOptions())
print(data)
} catch {
print ("Error")
}
urlRequest.HTTPBody = data
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlRequest, completionHandler:{ data, response, error in
guard error == nil else {
print("ERROR: Cannot call Get on endpoint")
print(error)
return
}
guard let responseData = data else {
print("ERROR: Did not receive any data")
return
}
print("DATA: \(data)")
})
task.resume()
}
You could do something like
let jsonObj = [...]
var data = NSData()
do {
data = try NSJSONSerialization.dataWithJSONObject(jsonObj, options: .PrettyPrinted)
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)!
} catch {
print("error: \(error)")
}
*Tried on Swift 2 & Xcode 7.3.1

Resources