Alamofire parameters based on value - swift

I'm posting parameters to my API with Alamofire.
I'm trying to use different parameters based on if we have a password or not. See a part of my code below:
let parameters: [String: Any] = [:]
if (password != nil) {
let parameters: [String : Any] = [
"displayName": firstName + " " + lastName,
"firstName": firstName,
"lastName": lastName,
"password": password ?? "",
"passwordConfirmation": password ?? "",
"location": location?.json ?? [:],
"wallet": wallet?.json ?? [:],
"gender": gender.rawValue,
"avatarId": 1,
"email": email,
"authExternalAccessToken": accessToken ?? "",
]
} else {
let parameters: [String : Any] = [
"displayName": firstName + " " + lastName,
"firstName": firstName,
"lastName": lastName,
"password": password ?? "",
"passwordConfirmation": password ?? "",
"location": location?.json ?? [:],
"wallet": wallet?.json ?? [:],
"gender": gender.rawValue,
"avatarId": 1,
"email": email,
"authExternalAccessToken": accessToken ?? "",
]
}
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: [
when I set a breakpoint behind the if/else statement it says there are 0 elements. What am I doing wrong? I can probably also speed this up as it takes longer to build this way.

In if-else block you are creating new constant parameters, so change your code like this.
let parameters: [String: Any]
if (password != nil) {
parameters = [
"displayName": firstName + " " + lastName,
"firstName": firstName,
"lastName": lastName,
"password": password ?? "",
"passwordConfirmation": password ?? "",
"location": location?.json ?? [:],
"wallet": wallet?.json ?? [:],
"gender": gender.rawValue,
"avatarId": 1,
"email": email,
"authExternalAccessToken": accessToken ?? "",
] as [String : Any]
} else {
parameters = [
"displayName": firstName + " " + lastName,
"firstName": firstName,
"lastName": lastName,
"password": password ?? "",
"passwordConfirmation": password ?? "",
"location": location?.json ?? [:],
"wallet": wallet?.json ?? [:],
"gender": gender.rawValue,
"avatarId": 1,
"email": email,
"authExternalAccessToken": accessToken ?? "",
] as [String : Any]
}

You are redeclaring your parameters variable rather then assigning to it.
You can only assign to a let variable a single time, however that assignment does not have to occur as part of the same statement as the declaration.
For example:
let parameters: [String: Any]
if (password != nil) {
parameters = [
"displayName": firstName + " " + lastName,
"firstName": firstName,
"lastName": lastName,
"password": password ?? "",
"passwordConfirmation": password ?? "",
"location": location?.json ?? [:],
"wallet": wallet?.json ?? [:],
"gender": gender.rawValue,
"avatarId": 1,
"email": email,
"authExternalAccessToken": accessToken ?? "",
]
} else {
parameters = [
"displayName": firstName + " " + lastName,
"firstName": firstName,
"lastName": lastName,
"password": password ?? "",
"passwordConfirmation": password ?? "",
"location": location?.json ?? [:],
"wallet": wallet?.json ?? [:],
"gender": gender.rawValue,
"avatarId": 1,
"email": email,
"authExternalAccessToken": accessToken ?? "",
]
}
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: [

Related

"Swift" Parse json .. getting response but not true in swift 5

This is input of Api:
{
"key" : "1", // Questionnaire response : key
"answer" : { // Questionnaire response : options value
"0":"19 to 27,10",
"1":"Below 5 years,10",
"2":"Second class upper & above,10",
"3":"Yes,10",
"4":"Below 2 years,10"
}
}
This is func when iam calling Api:
func callEligibility(with model: [VisaEligibility], completion: #escaping(Result<[VisaEligibility], Error>)-> ()) {
guard let url = URL(string: eligibility_url)
else {
return }
let body: [String: Any] = [
"key": model[0].key,
"answer": model[0].answer
]
let finalBody = try? JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.allHTTPHeaderFields = ["Token":"birdview#v1"]
URLSession.shared.dataTask(with: request){
(data , response, error) in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
completion(.failure(error?.localizedDescription as! Error))
return
}
guard let response = response else {
return
}
print(response)
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}.resume()
}
This is Model:
struct VisaEligibility: Codable, Hashable {
let key: String
let answer: [String: String]
}
This are answer outputs:
["[\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]": "[\"22 to 29\", \"Bachelor’s degree\", \"Yes\", \"Yes\", \"Yes\", \"3 years or more\", \"Yes\"],[\"20\", \"5\", \"10\", \"0\", \"0\", \"5\", \"5\"]"]
["0", "1", "2", "3", "4", "5", "6"],["22 to 29", "Bachelor’s degree", "Yes", "Yes", "Yes", "3 years or more", "Yes"],["20", "5", "10", "0", "0", "5", "5"]
This are my answer input
Here I am calling Api,
QuestionCount,QuestionName and QuestionPoins are my textfields text
let answerr = ["\(questionCounts)":"\(questionNames),\(questionPoints)"]
let model = [VisaEligibility(key: "45", answer: answerr)]
ApiManager.shared.callEligibility(with: model) { result in
switch result {
case.success(let answ):
print(answ)
self.eligiblity = answ
self.percentLabel.text = answ[0].key
case.failure(let error):
print(error)
}
}
When iam calling api it should calculate my textfieldt text each of text has own point
and it shuold return answer.but it just shows result is 0%
Headers {
"Cache-Control" = (
"no-store, no-cache, must-revalidate"
);
Connection = (
"Keep-Alive"
);
"Content-Type" = (
"text/html; charset=UTF-8"
);
Date = (
"Thu, 08 Sep 2022 13:12:35 GMT"
);
Expires = (
"Thu, 19 Nov 1981 08:52:00 GMT"
);
"Keep-Alive" = (
"timeout=5, max=100"
);
Pragma = (
"no-cache"
);
Server = (
Apache
);
"Transfer-Encoding" = (
Identity
);
} }
["code": 200, "result": 0%]
when iam calling it in postmant it shows me true result.
what should i do?
this is questions api's input which i am calling questions
and after calling questions i have to pass them like dictionary to another api for to get result
{
"code": "200",
"result": [
{
"key": "2",
"questions": [
{
"key": "0",
"question": "How old are you? ",
"options": [
{
"option": "22 to 29",
"point": "20",
"plus": 0
},
{
"option": "30 to 34",
"point": "10",
"plus": 0
},
**problem is in my textfields give's me**
Count["[\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]":Name"[\"22 to 29\", \"Bachelor’s degree\", \"Yes\", \"Yes\", \"Yes\", \"3 years or more\", \"Yes\"],[\"20\", \"5\", \"10\", \"0\", \"0\", \"5\", \"5\"]"]
**Point**["0", "1", "2", "3", "4", "5", "6"],["22 to 29", "Bachelor’s degree", "Yes", "Yes", "Yes", "3 years or more", "Yes"],["20", "5", "10", "0", "0", "5", "5"]
but i need they should be.
**["0":"22 to 29 , 20" ]**
**[TfCount first:TfName first,Tfpoint first]**

Alamofire JSON parsing of dictionary of arrays

Trying to parse this dictionary of Arrays.
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna#melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
}
]
Is it possible to parse this Dictionary of arrays into an array of Model ([Artist]) for convenience.
AF.request(Constants.kGetArtistsAPIEndPoint).responseDecodable(of: [ArtistsResponse].self) { (response) in
guard let artistsResponse = response.value else { return }
print("ArtistsResponse is \(artistsResponse)")
if let artists = artistsResponse.first {
completion(artists)
}
}
My Artist class looks like below
struct ArtistsResponse: Codable {
let artists: [Artist]
}
struct Artist: Codable {
let artistId: String
let name: String
let username: String?
let emailId: String?
let address: Address?
let phone: String?
let website: String?
let company: Company?
enum CodingKeys: String, CodingKey {
case artistId = "id"
case name
case username
case emailId
case address
case phone
case website
case company
}
}
struct Address: Codable {
let street: String
let suite: String?
let city: String
let zipcode: String
let geo: GeoLocation
enum CodingKeys: String, CodingKey {
case street
case suite
case city
case zipcode
case geo
}
}
struct GeoLocation: Codable {
let latitude: Double
let longitude: Double
enum CodingKeys: String, CodingKey {
case latitude = "lat"
case longitude = "lng"
}
}
Tried with above code but it fails with below error code
Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: Swift.DecodingError.typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))))

Multipart Form Data POST with spesific JSON Requirement

I'm new to Alamofire and now using Alamofire 5. I want to create a POST request with multipart form data, but there's a specific requirement for the JSON body. Here it is:
"item": [
{
"name": "Upload image",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "files[]",
"type": "file",
"src": []
},
{
"key": "mode",
"value": "public",
"type": "text"
}
]
},
"url": {
"raw": "https://jsonplaceholder.typicode.com/api/image/upload",
"protocol": "https",
"host": [
"jsonplaceholder",
"typicode",
"com"
],
"path": [
"api",
"image",
"upload"
]
}
},
"response": []
},
]
Anyone can help me how to post the data but with multipart form data? Please help.
(It's okay if the POST request is using URLSession)
Whatever I understand from your question and comments, I have created a method from your previous question.
func postImage(images: [UIImage],imgName : [String]) {
var arrFormData = [[String:Any]]()
var imgDataArray: [Data] = []
for image in images {
guard let imgData = image.jpegData(compressionQuality: 0.50) else { return }
imgDataArray.append(imgData)
}
let param1: [String: Any] = [
"key":"files[]",
"type": "file",
"src": imgName
]
let param2: [String: Any] = [
"key": "mode",
"value": "public",
"type": "text"
]
var arrParam = [[String:Any]]()
arrParam.append(param1)
arrParam.append(param2)
arrFormData.append(contentsOf: arrParam)
var param : [String:Any] = [:]
if let theJSONData = try? JSONSerialization.data(
withJSONObject: arrFormData,
options: []) {
let theJSONText = String(data: theJSONData,
encoding: .ascii)
print("JSON string = \(theJSONText!)")
param = ["formData" : theJSONText ?? ""]
}
print(param)
Alamofire.upload(multipartFormData: {
multipartFormData in
for i in 0..<images.count{
if let imageData = images[i].jpegData(compressionQuality: 0.6) {
multipartFormData.append(imageData, withName: "file", fileName: "name.png", mimeType: "image/png")
}
}
for (key, value) in param {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, usingThreshold: 10 * 1024 * 1024,to: apiurl, method: .post, headers: headers, encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON {
response in
print(response.result)
}
case .failure(let encodingError):
print(encodingError)
}
})
}

Codable Issue If Dictionary is Empty

I am trying to make use of Codable protocol with swift
Issue is I need to dequeue nested dictionary getting from server. Suppose
Data : its values and inside data one more dictionary Goal
if goal inside data has a value it works fine
but in case goal inside Dictionary turns out to be empty it says
Error - The data couldn’t be read because it isn’t in the correct format.
My JSON Response
case 1 - Without Goal - Issue facing
{
"code": "1",
"message": "Data fetched successfully",
"data": {
"id": "2",
"organization_id": "2",
"first_name": "iOS",
"last_name": "test",
"user_name": "iOS",
"email": "ios#gmail.com",
"password": "4399578cc31cf62535a7dba566e4aea0",
"security_hash": "fdf4d3bb5731de23b42771e01d9e0c3e",
"google_id": "525256562",
"facebook_id": "525256562",
"access_code": "iosTest1",
"gender": "",
"contact": "1234567890",
"user_profile": "",
"profile_thumb": "",
"dob": "",
"weight": "",
"height": "",
"is_corporate": "0",
"status": "1",
"created_at": "2018-04-19 10:37:46",
"updated_at": "2018-12-10 15:32:59",
"profile_image_url": "",
"goal": {}
}
}
case 2: When Goal has values
{
"code": "1",
"message": "Data fetched successfully",
"data": {
"id": "2",
"organization_id": "2",
"first_name": "iOS",
"last_name": "test",
"user_name": "ios",
"email": "ios#gmail.com",
"password": "4399578cc31cf62535a7dba566e4aea0",
"security_hash": "fdf4d3bb5731de23b42771e01d9e0c3e",
"google_id": "525256562",
"facebook_id": "525256562",
"access_code": "iosTest1",
"gender": "",
"contact": "1234567890",
"user_profile": "",
"profile_thumb": "",
"dob": "",
"weight": "",
"height": "",
"is_corporate": "0",
"status": "1",
"created_at": "2018-04-19 10:37:46",
"updated_at": "2018-12-10 15:32:59",
"profile_image_url": "",
"goal": {
"id": "4",
"client_id": "2",
"ambition_to_achieve": "adfadf",
"current_assessment": "dfadfafa",
"expected": "fasdfasdfsafsf",
"expected_date": "2018-12-15",
"description": "asdfadsfadf",
"goal_status": "1",
"created_at": "2018-12-12 18:15:36",
"updated_at": ""
}
}
}
///--- Main Class Which handle main Data
struct LoggedUser: Codable {
var dob, weight, height: String?
let accesscode, contact, contactcode, email, facebookid: String?
let firstname, gender, googleid, id, iscorporate, lastname: String?
let organizationid, password, profilethumb, securityhash, status: String?
let username, userprofile : String?
let goal:Goal?
enum CodingKeys: String, CodingKey {
case accesscode="access_code"
case contact, dob, email, gender, height, id, password, status, weight, goal
case contactcode="contact_code"
case facebookid="facebook_id"
case firstname="first_name"
case googleid="google_id"
case iscorporate="is_corporate"
case lastname="last_name"
case organizationid="organization_id"
case profilethumb="profile_thumb"
case securityhash="security_hash"
case username="user_name"
case userprofile="user_profile"
}
}
/// ---> Class For Goal
struct Goal: Codable {
let id, clientID, ambitionToAchieve, currentAssessment: String?
let expected, expectedDate, description, goalStatus: String?
let createdAt, updatedAt: String?
enum CodingKeys: String, CodingKey {
case id
case clientID = "client_id"
case ambitionToAchieve = "ambition_to_achieve"
case currentAssessment = "current_assessment"
case expected
case expectedDate = "expected_date"
case description
case goalStatus = "goal_status"
case createdAt = "created_at"
case updatedAt = "updated_at"
}
}
----> Update
Just a correction
Posting actual response
Get My Goal API Response ==> ["code": 1, "message": Data fetched successfully, "data": {
"access_code" = iosTest4;
contact = 1111111111;
"contact_code" = 91;
"created_at" = "2019-02-12 14:42:34";
dob = "1996-05-10";
email = "testing#email.com";
"facebook_id" = "";
"first_name" = iOS;
gender = 1;
goal = (
);
"google_id" = "";
height = "5.10";
id = 35;
"is_corporate" = 0;
"last_name" = test;
"organization_id" = 0;
password = 915729f1e48bda300dabaac7d1ac8358;
"profile_image_url" = "";
"profile_thumb" = "";
"security_hash" = 991f5cd86be6fc485633d1946dc84a7a;
status = 1;
"updated_at" = "2019-02-14 16:25:01";
"user_name" = "testing#email.com";
"user_profile" = "";
weight = "0.10";
}]
As I was getting 2 Different Formats
when Goal is empty it gives me an array
when had some value it returns a Dictionary
So I Explicitly Created my Own Data() by manually Casting goal as [String:Any]
var loginDataDict = jsonDict["data"] as! [String:Any]
if let goalData = loginDataDict["goal"] as? [String:Any] {
loginDataDict.updateValue(goalData, forKey: "goal")
} else {
loginDataDict.updateValue([:], forKey: "goal")
}
This Might not be a proper solution but may help someone if having same scenario as I had here

How to fetch the following data into the tableview using Swift?

First lets see the json data.
[
{
"id": "244",
"name": "PIZZAS",
"image": "",
"coupon": "1",
"icon": "",
"order": "1",
"aname": "",
"options": "2",
"subcategory": [
{
"id": "515",
"name": "MARGARITA",
"description": "Cheese and Tomato",
"image": "",
"icon": "",
"coupon": "1",
"order": "1",
"aname": "",
"options": "2",
"item": [
{
"id": "1749",
"name": "9 Inch Thin & Crispy Margarita",
"description": "",
"price": "3.40",
"coupon": "1",
"image": "",
"options": "2",
"order": "1",
"addon": "495",
"aname": "",
"icon": ""
}]
}]
}]
I have used Alamofire and getting response through this code below:
Alamofire.request(.GET, myUrl, parameters:nil , encoding: .JSON)
.validate()
.responseString { response in
print("Response String: \(response.result.value)")
}
.responseJSON { response in
print("Response JSON: \(response.result.value)")
if let jsonResult = response as? Array<Dictionary<String,String>> {
let Name = jsonResult[0]["name"]
let ID = jsonResult[0]["id"]
let Order = jsonResult[0]["order"]
print("JSON: Name: \(Name)")
print("JSON: ID: \(ID)")
print("JSON: Order: \(Order)")
}
}
But after getting response data I am not able to get any value. Here I want to fetch all data like name,id and subcategory - how to implement this?
You have more than one problem there.
First response is of type Response<Anyobject, NSError>, it's not the parsed object you're looking for, instead you should use response.result.value as you did for the log.
Second even if you tried to cast response.result.value to Array<Dictionary<String,String>> it will not pass because in your json data you have ann inner array subcategory which cannot be casted to Dictionary<String, String>
This code should work for you:
Alamofire.request(.GET, myUrl, parameters:nil , encoding: .JSON)
.validate()
.responseString { response in
print("Response String: \(response.result.value)")
}
.responseJSON { response in
print("Response JSON: \(response.result.value)")
let array = response.result.value as! Array<NSDictionary>
for item in array
{
let Name = item["name"]
let ID = item["id"]
let Order = item["order"]
let Subcategories = item["subcategory"] as! Array<NSDictionary>
for subCategory in Subcategories
{
let subId = subCategory["id"]
}
}
}
And here is the results in the playground:
Cheers.