Handle API response without dictionary key parameter SWIFT - ios

I try to decode api response but the values did not have key. How can I decode values to my entity ? I can get values but how can I map values to array of object?
Here is my code:
if let encoded = urlString.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed), let url = URL(string: encoded) {
AF.request(url, method: .get, encoding: JSONEncoding.default).validate().responseData { (response) in
switch response.result {
case .success:
print("Validation Successful)")
if let json = response.data {
do{
let asJSON = try JSONSerialization.jsonObject(with: json, options: []) as? [String: Any]
let dataArray = asJSON?["states"] as? [NSArray]
guard let data = dataArray else { return }
for (i, flight) in data.enumerated() {
for first in flight.enumerated() {
print(first)
}
}
}
catch{
print("JSON Error")
}
}
case .failure(let error):
print(error.errorDescription)
}
}
}
And this is my print
(
4baa88,
"THY3TB ",
Turkey,
1669746477,
1669746477,
"28.782",
"40.9959",
"1127.76",
0,
"118.94",
"301.56",
"-6.5",
"<null>",
"1196.34",
"<null>",
0,
0
)
And this is example of my response
{
"time": 1669744917,
"states": [
[
"4bc855",
"PGT4AE ",
"Turkey",
1669744917,
1669744917,
28.1582,
41.0447,
5791.2,
false,
181.16,
119.99,
-5.85,
null,
5913.12,
"7554",
false,
0
],
[
"4bc846",
"PGT4BC ",
"Turkey",
1669744916,
1669744916,
28.2241,
40.8712,
5608.32,
false,
216.41,
168.34,
-13.33,
null,
5722.62,
"7703",
false,
0
]
]

Related

JSON parameter in multipart form PUT request in iOS Swift using AlmoFire

I want to upload image using Multipart/formdata put request in iOS Swift using Almofire Networking which has few parameters and one parameter contains JSON. e.g
"parameter_name":{
"field_1" : {
"type" : "MULTISELECT",
"value" : [
"Option 1",
"Option 3"
],
"name" : "Multi Selection"
},
"field_2" : {
"type" : "DATE",
"name" : "BirthDate",
"value" : "2000-09-08"
},
"field_3" : {
"type" : "SINGLESELECT",
"value" : "Option1",
"name" : "Single Select"
}
}
This is one parameter in multipart formdata with other parameters like name, email, photo and more (all are of type string)
Could anyone help me achieving this as using Swift & AlamoFire As I am receiving 503 status code for this.
Note:- In postman same API is working fine.
What I have done so far is:
Alamofire.upload(multipartFormData: { multipartData in
parameters.forEach { (key, value) in
if let arrdata = (value as? [AnyHashable : Any]) {
if arrdata.count > 0 {
let arrdatas = try! JSONSerialization.data(withJSONObject: arrdata, options: [])
multipartData.append(arrdatas, withName: key as String)
}
}
guard
let data = (value as? String)?
.data(using: .utf8)
else { return }
multipartData.append(data, withName: key)
}
if let img = photo,
let data = UIImageJPEGRepresentation(img, 0.0) {
multipartData
.append(data,
withName: Keys.photo,
fileName: Keys.fileName,
mimeType: Keys.mimeType)
}
},
to: "My URL",
headers: requestType.headers,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseData(completionHandler: { response in
if let statusCode = response.response?.statusCode,
200 <= statusCode && statusCode < 300,
let data = response.data {
guard
let decoded = try? JSONSerialization.jsonObject(with: data, options: []),
let dic = decoded as? [String: Any] else {
return
}
printOnlyOnDebug("Response got is --> \(self.convertToJSON(toConvert: dic))")
success(data)
} else {
guard
let data = response.data,
let decoded = try? JSONSerialization.jsonObject(with: data, options: []),
let dic = decoded as? [String: Any],
let message = dic[Keys.message] as? String else {
let code = response.response?.statusCode == 503 ? 401 : response.response?.statusCode
failure(code, "Network error")
return
}
failure(response.response?.statusCode, message)
}
})
case .failure(let error):
failure(nil, error.localizedDescription)
}
})
Also header contains 'Content-Type' as 'multipart/form-data'
I forgot to mention method type PUT in AlamoFire request so it was creating POST request and it was causing the issue.
Alamofire.upload(multipartFormData: { multipartData in
parameters.forEach { (key, value) in
if let arrdata = (value as? [AnyHashable : Any]) {
if arrdata.count > 0 {
let arrdatas = try! JSONSerialization.data(withJSONObject: arrdata, options: [])
multipartData.append(arrdatas, withName: key as String)
}
}
guard
let data = (value as? String)?
.data(using: .utf8)
else { return }
multipartData.append(data, withName: key)
}
if let img = photo,
let data = UIImageJPEGRepresentation(img, 0.0) {
multipartData
.append(data,
withName: Keys.photo,
fileName: Keys.fileName,
mimeType: Keys.mimeType)
}
},
to: "My URL",
method:.put,
headers: requestType.headers,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseData(completionHandler: { response in
if let statusCode = response.response?.statusCode,
200 <= statusCode && statusCode < 300,
let data = response.data {
guard
let decoded = try? JSONSerialization.jsonObject(with: data, options: []),
let dic = decoded as? [String: Any] else {
return
}
printOnlyOnDebug("Response got is --> \(self.convertToJSON(toConvert: dic))")
success(data)
} else {
guard
let data = response.data,
let decoded = try? JSONSerialization.jsonObject(with: data, options: []),
let dic = decoded as? [String: Any],
let message = dic[Keys.message] as? String else {
let code = response.response?.statusCode == 503 ? 401 : response.response?.statusCode
failure(code, "Network error")
return
}
failure(response.response?.statusCode, message)
}
})
case .failure(let error):
failure(nil, error.localizedDescription)
}
})

Crash while uploading image using Alamofire

I'm uploading an image using Alamofire like so..
EDIT: This is the edited code...
for img in images {
let url = "http:my url"
let headers = [
"Accept": "application/json",
"Authorization": self.accessToken
]
if let imageData = (UIImageJPEGRepresentation(img, 0.6)) {
let parameters: [String: String] =
[
"seller_id": "\(self.mySellerId)",
"offline_id": self.prodID,
"is_default": "1",
"sequence": "\(sequenceCount)"
]
Alamofire.upload(multipartFormData: {(multipartFormData) in
let filePath = NSURL(fileURLWithPath: url)
print(imageData)
multipartFormData.append (imageData, withName: "image", fileName: "\(Date().timeIntervalSince1970).jpg", mimeType: "image / jpg")
for (key, value ) in parameters {
print(key,value)
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}
}, to: url, method: .post, headers: headers)
{ (result) in
switch result {
case .success(let upload, _,_ ):
upload.uploadProgress(closure: { (progress) in
UILabel().text = "\((progress.fractionCompleted * 100)) %"
print (progress.fractionCompleted * 100)
})
upload.responseJSON { response in
if let JSON = response.result.value {
print(JSON)
}else{
print("Error")
}
}
case .failure(let encodingError):
print(encodingError)
break
}
}
}
}
In the part for (key, value) in parameters... the for loop goes through all values. But when it reaches the image data part, it crashes saying Could not cast value of type 'Foundation.Data' (0x10787b9f0) to 'Swift.String'
What should be given instead so that the error can be fixed..?
You are casting all values from parameters dictionary as String's, first entry in dictionary is "product_image" and it has imageData as value and that is of type Data.
I would do this, no more force casting.
for (key, value) in parameters {
if let v = value as? String, let valueAsData = v.data(using: .utf8) {
multipartFormData.append(valueAsData, withName: key )
}
}
You could also check if value is already Data type and just add it as well like:
for (key, value) in parameters {
var dataToAppend: Data?
if let data = value as? Data {
dataToAppend = data
} else if let v = value as? String, let valueAsData = v.data(using: .utf8) {
dataToAppend = valueAsData
}
if let d = dataToAppend {
multipartFormData.append(d, withName: key )
}
}

Alamofire .post api error: Code=3840 "Invalid value around character 1

Using Alamofire for .post api, api giving data in postman but not in my code. Posting below the code, please guide what wrong i am doing here:
// API calling method:
parameters = [
"Address" : "" as AnyObject,
"Name" : "" as AnyObject,
"ServiceID" : "" as AnyObject,
"Rating" : "" as AnyObject,
"Price" : "" as AnyObject
]
let headers: Dictionary = [
"" : ""
]
print(parameters)
ApiServices.requestPOSTURL(strURL, params: parameters, headers: headers, success:{
(JSONResponse) -> Void in
CommonMethodsClass.hideHUD(targetView: self.view)
print(JSONResponse["message"])
let strMsg = JSONResponse["message"].stringValue
if (JSONResponse["status"].intValue == 1)
{
}
else
{
CommonMethodsClass.showAlertMessage(vc: self, titleStr: "Error!", messageStr: strMsg)
}
}) {
(error) -> Void in
print(error)
CommonMethodsClass.hideHUD(targetView: self.view)
}
// Api request method:
class func requestPOSTURL(_ strURL : String, params : [String : AnyObject]?, headers : [String : String]?, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void){
Alamofire.request(strURL, method: .post, parameters: params, encoding: JSONEncoding.default).responseJSON { (responseObject) -> Void in
print(responseObject)
if responseObject.result.isSuccess {
let resJson = JSON(responseObject.result.value as Any)
success(resJson)
}
if responseObject.result.isFailure {
let error : Error = responseObject.result.error!
failure(error)
}
}
}
Error: FAILURE:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
1." UserInfo={NSDebugDescription=Invalid value around character 1.}))
Update: Response to parse, may also needs to be changed.
{
"status": true,
"message": "",
"data": [
{
"SalonID": "1",
"SalonName": "Affinity",
"SalonEmail": "vay.chaan#th-rce.com",
"SalonPhone": "9999888877",
"SalonMobile": "9999888877",
"SalonAddress": "C-28, Sec-58, India",
"Latitude": "18.5806",
"Longitude": "27.36273",
"Image": null,
"SalonImage": "",
"TimeIntervalminutes": 20,
"AverageRating": 4,
"IsActive": 1
},
{
"SalonID": "3",
"SalonName": "Looks",
"SalonEmail": "rad#th-rce.com",
"SalonPhone": "99998828877",
"SalonMobile": "99998388877",
"SalonAddress": "GP Mall,India",
"Latitude": "",
"Longitude": "",
"Image": null,
"SalonImage": "",
"TimeIntervalminutes": 30,
"AverageRating": 5,
"IsActive": 1
}
]
}
Replace responseJSON with responseString.
You need to convert the string for values. Can you update the string in your question?
You can use this function to convert response string into JSON:
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
String: let str = "{\"name\":\"James\"}"
USAGE: let dict = convertToDictionary(text: str)
Try responseString instead of responseJSON and it will work
Alamofire.request("URL").responseString { response in
print(response)
if let json = response.result.value {
print("JSON: \(json)")
}
}
Change responseJSON to responseString and it will work :)
Alamofire.request("URL").responseString { response in
print(response)
if let json = response.result.value {
print("JSON: \(json)")
}
}

How to send json as parameter iOS swift?

I want to send following object as body parameter. But serialization is failing:
{
"StartAddress":"Colombo",
"EndAddress":"Kandy",
"DepartureAddress":"Kollupitiya, Colombo",
"ArrivalAddress":"Peradeniya, Kandy",
"CreatedDate":"2017-07-30",
"Date":"2017-07-30",
"Time":"2017-07-30",
"IsLadiesOnly":true,
"IpAddress":"fe80::8638:38ff:fec8:ea50%wlan0",
"Country":"Srilanka",
"VehicleId":"1129",
"StartLocation":[
6.9270974,
79.8607731
],
"EndLocation":[
7.2916216,
80.6341326
],
"Points":"k}gi#y{lf",
"Route":{
"Bounds":{
"NorthEast":[
7.2916216,
80.6341326
],
"SouthWest":[
6.9270974,
79.8607731
]
},
"Legs":[
{
"LegId":1,
"Distance":14904,
"Duration":1941,
"StartAddress":"Colombo",
"EndAddress":"Kadawatha",
"StartLocation":[
6.9270974,
79.8612478
],
"EndLocation":[
7.0011125,
79.95000750000001
],
"Ancestors":[
],
"Price":745
},
{
"LegId":2,
"Distance":63040,
"Duration":6209,
"StartAddress":"Kadawatha",
"EndAddress":"Kegalle",
"StartLocation":[
7.0011125,
79.95000750000001
],
"EndLocation":[
7.251436200000001,
80.3466076
],
"Ancestors":[
"Colombo"
],
"Price":3152
},
{
"LegId":3,
"Distance":38990,
"Duration":4430,
"StartAddress":"Kegalle",
"EndAddress":"Kandy",
"StartLocation":[
7.251436200000001,
80.3466076
],
"EndLocation":[
7.2901864,
80.6338425
],
"Ancestors":[
"Colombo",
"Kadawatha"
],
"Price":1950
}
]
},
"TotalPrice":"5847.0",
"SeatCount":1,
"Detour":1,
"Luggage":2,
"DetoursDescription":"10 Minutes",
"LuggageDescription":"Small Luggage",
"Notes":"new ride"
}
when I try to serialize it before send it gives an error:
'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization
dataWithJSONObject:options:error:]: Invalid top-level type in JSON
write'
func synchronusPostRequstWithHeadersJson(apiMethod:String, params:JSON, headers:[ String: String]) -> ResultModel {
let resultModel = ResultModel()
//create the url with URL
let url = URL(string: BASE_URL + apiMethod )!
let session = URLSession.shared
//// **** HERE IT FAILING *****////
let jsonData = try? JSONSerialization.data(withJSONObject: params)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
for item in headers {
request.addValue(item.value, forHTTPHeaderField: item.key)
}
let semaphore = DispatchSemaphore(value: 0)
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
if(error != nil){
resultModel.ErrorType = .NO_INT
resultModel.JsonReslut = JSON.null
}else{
if let resp = response as? HTTPURLResponse{
if(resp.statusCode == 200){
if let jsonResult = JSON(data) as? JSON {
resultModel.ErrorType = .NO_ERROR
resultModel.JsonReslut = jsonResult
}
}else{
if let jsonResult = JSON(data) as? JSON {
resultModel.ErrorType = .SEREVR_ERROR
resultModel.JsonReslut = jsonResult
}else{
resultModel.ErrorType = .SEREVR_ERROR
resultModel.JsonReslut = JSON.null
}
}
}
}
semaphore.signal()
})
task.resume()
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
return resultModel
}
How can i send that request?. Is it possible with alamofire?
Using Almofire you can achieve this as
let params: [String: Any] = [
"StartAddress":"Colombo",
"EndAddress":"Kandy",
"DepartureAddress":"Kollupitiya, Colombo",
"StartLocation":[
6.9270974,
79.8607731
],
"EndLocation":[
7.2916216,
80.6341326
],
] //Do check your dictionary it must be in correct format
Alamofire.request("yourUrl", method: .post, parameters: params, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
}
try using:
let session = Foundation.URLSession.shared
let url = URL(string: "Your server url")
var request = URLRequest(url : url!)
request.httpMethod = "POST"
let params :[String:Any] = ["name":"yuyutsu" as Any,"rollno":12 as Any] //Add your params
do {
let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
session.dataTask(with: request, completionHandler: { data, response, error in
OperationQueue.main.addOperation {
guard error == nil && data != nil else { // check for fundamental networking error
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
// print("response = \(response)")
}
let responseString = String(data: data!, encoding: String.Encoding.utf8)
print("responseString = \(responseString!)")
if let responsedata = responseString!.data(using: String.Encoding.utf8)! as? Data{
do {
let jsonResult:NSDictionary = try JSONSerialization.jsonObject(with: responsedata, options: []) as! NSDictionary
print("Get The Result \(jsonResult)")
if error != nil {
// print("error=\(error)")
}
if let str = jsonResult["success"] as? NSNull {
print("error=\(str)")
}
else {
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("Response string : \(responseString)")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
}) .resume()
}catch {
// print("Error -> \(error)")
}
hope this might help you out.
Creating JSON parameters to send it as a post body:
Function:
//MARK:- Create JSON String
func createJSONParameterString(postBody:AnyObject) -> String {
if let objectData = try? JSONSerialization.data(withJSONObject: postBody, options: JSONSerialization.WritingOptions(rawValue: 0)) {
let objectString = String(data: objectData, encoding: .utf8)
return objectString ?? ""
}
return ""
}
Usage:
var postBody = [AnyHashable:Any]()
postBody["device_id"] = "device_ID"
let parameters = createJSONParameterString(postBody: postBody as AnyObject)
print(parameters)
i have solved similar problem using Alamofire and SwiftyJson as follow
let call your object (data )
let json = JSON(data)
let Params :Dictionary = json.dictionaryObject!
and in Alamofire request
Alamofire.request(url, method: .post, parameters: Params , encoding: JSONEncoding.prettyPrinted, headers: nil)
//.validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result
{
case .failure(let error):
case .success(let value):
}
it need to replace this "{ }" with "[ ]"
and alamofire and swift json handle that issue
ex:
[
{
"firstName" : " " ,
"lastName" : " "
},
{
"firstName" : " " ,
"lastName" : " "
}
]
change it to
[
[
"firstName" : " " ,
"lastName" : " "
],
[
"firstName" : " " ,
"lastName" : " "
]
]

swiftyjson getting string from json array

I am using alamofire and swiftyjson to get it. I need to get string "ubus_rpc_session", I tryed this way, but I get an array, I need to get string. Could you help me?
Alamofire.request(URL, method: .post, parameters: param, encoding: JSONEncoding.default).responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
let token = json["result"].arrayValue.map({$0["ubus_rpc_session"].stringValue})
print(token)
{ "jsonrpc":"2.0",
"id":1,
"result":[
0,
{
"ubus_rpc_session":"07e111d317f7c701dc4dfde1b0d4862d",
"timeout":300,
"expires":300,
"acls":{
"access-group":{
"superuser":[
"read",
"write"
],
"unauthenticated":[
"read"
]
},
"ubus":{
"*":[
"*"
],
"session":[
"access",
"login"
]
},
"uci":{
"*":[
"read",
"write"
]
}
},
"data":{
"username":"root"
}
}
]
}
Try this
//Getting an array of string from a JSON Array(In their documents)
let arrayNames = json["users"].arrayValue.map({$0["name"].stringValue})
if let tempArray = json["result"].arrayValue {
for item in tempArray {
print(item)
if let title = item["ubus_rpc_session"].string {
println(title)
}
}
}
Or check this
let value = tempArray[1].dictionaryObject!
print(value["ubus_rpc_session"]!)

Resources