how to define nested dictionary for alamofire POST request - ios

Hi I have a nested dictionary that I need to pass to a function to make a POST request using alamofire.
this is the function that conduct the API call
func apiCall(productParameter: [String:String]) {
AF.request(dataURL, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
debugPrint(response)
//some other code here.
}
}
in my viewController, I need to call this function:
apiCall(productParameter: [String:String])
the problem is I have a very complicated nested dictionary to pass... like this :
{
"userId": "string",
"price": {
"currency": "USD",
"amount": 99.96
},
"paymentModel": "string",
"description": "string",
"product": [
{
"description": "string",
"name": "string",
"images": [
"string"
]
}
]
}
do you know how to define the function and data type? thanks.

You should try [String : Any] in this case, so that your keys are always Strings but the values can be Strings, Dictionarys, Arrays and so on.

Related

How can I convert JSON to Swift Dictinary inorder to make an HTTP POST

I am having issues to successfully structure my json data into a swift dictionary inorder to send my HTTP body via an API
This is how my Json is structured:
{
"idNo": "string",
"name": "string",
"isRegistered": true,
"customMessage": "string",
"riskStatus": "Low",
"exposureBasedRiskStatus": "Low",
"symptomBasedRiskStatus": "Low",
"riskMessage": "string",
"doYouHaveATemperature": true,
"temperature": 0,
"asessmentQuestion": [
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
}
]
}
the object "asessmentQuestion" is an array of different questions, can't seem to figure out how to convert this structure to a swift dictionary or another recommended format for me to be able to post my data. My API is always saying bad request and I'm pretty sure I am not correctly mapping the json data.
this is a snippet of how I am attempting to map my json data:
var dictionary = [String:Any]()
dictionary["1. How old are you?"] = model.riskExposureBasedAssessment[0].answer
dictionary["2. Have you ever visited a COVID affected country?"] = model.riskExposureBasedAssessment[1].answer
dictionary["3. do you frequently experience flu like symptoms?"] = model.riskExposureBasedAssessment[2].answer
dictionary["4. Where you providing care in a non-health setting for a person with symptomatic COVID-19 infection"] = model.riskExposureBasedAssessment[3].answer
dictionary["5. Did you come in close contact* with a person with symptomatic laboratory-confirmed COVID-19 infection?"] = model.riskExposureBasedAssessment[4].answer
let parameters = [
"idNo": model.id,
"name": model.name,
"isRegistered": model.isRegistered,
"customMessage": model.customResponse,
"riskStatus": model.riskStatus,
"exposureBasedRiskStatus": model.exposureBasedRiskStatus,
"symptomBasedRiskStatus": model.symptomBasedRiskStatus,
"riskMessage": model.riskMessage,
"doYouHaveATemperature": model.doYouHaveATemperature,
"temperature": model.temperature,
"exposureBasedAssessments": dictionary
] as [String:Any]
let postData = try? JSONSerialization.data(withJSONObject: parameters)
It's an array of dictionary, so :
var dictionaries: [[String: Any]] = []
// Populate dictionaries
// ...
let parameters = [
"idNo": model.id,
"name": model.name,
"isRegistered": model.isRegistered,
"customMessage": model.customResponse,
"riskStatus": model.riskStatus,
"exposureBasedRiskStatus": model.exposureBasedRiskStatus,
"symptomBasedRiskStatus": model.symptomBasedRiskStatus,
"riskMessage": model.riskMessage,
"doYouHaveATemperature": model.doYouHaveATemperature,
"temperature": model.temperature,
"exposureBasedAssessments": dictionaries
] as [String:Any]
Then, to populate it:
var dict1: [String: Any] = [:]
dict1["question"] = "1. How old are you?"
dict1["answer"] = model.riskExposureBasedAssessment[0].answer
dictionaries.append(dict1)
var dict2: [String: Any] = [:]
dict2["question"] = "2. Have you ever visited a COVID affected country?"
dict2["answer"] = model.riskExposureBasedAssessment[1].answer
dictionaries.append(dict2)
...
or
var dict1: [String: Any] = ["question": "1. How old are you?",
"answer": model.riskExposureBasedAssessment[0].answer]
dictionaries.append(dict1)
var dict2: [String: Any] = ["question": "2. Have you ever visited a COVID affected country?"",
"answer": model.riskExposureBasedAssessment[1].answer]
dictionaries.append(dict2)
...
But, I guess you have can retrieve the question from model.riskExposureBasedAssessment[n],
Instead of "1. How old are you?", can't you do model.riskExposureBasedAssessment[0].question?
If that's the case, you can use a for loop:
so I'd go with:
for aQuestionModel in model.riskExposureBasedAssessment {
let questionDict = ["question": aQuestionModel.question,
"answer": aQuestionModel.answer]
dictionaries.append(questionDict)
}
Or, once you master basic algorithm, closures, and map():
var dictionaries = model.riskExposureBasedAssessment.map { ["question": $0.question, "answer": $0.answer] }
It's missing the "createdBy", I don't know where to find it and if it's optional, but I think you should be able to add it if needed.
NotaBene:
Code not tested against a compiler. It should work, at maybe one or two typos.

How to decode a nested JSON struct with dynamic number of nested levels?

I can receive a JSON file with variable number of nested fields, like for example this:
{
"id": "field1",
"values": [{
"1": [{
"11": ["111", "112"],
"12": ["121", "122"]
}],
"2": [{
"21": ["211", "212"],
"22": ["221", "222"]
}]
]
}
so that would be decoded as [String: [String: [String]]]
or could be:
{
"id": "field1",
"values": [{
"1": ["11", "12"],
"2": ["21", "22"]
}]
}
so it would de decoded as [String: [String]], or could have one with even more nested levels ([String: [String: [String: [String]]]])... but I donĀ“t know the structure I will receive in beforehand.
Is it possible to handle this scenario?
Use Codable to get that working.
Model:
struct Root: Codable {
let id: String
let values: [[String:[[String:[String]]]]]
}
Parsing goes like,
do{
let response = try JSONDecoder().decode(Root.self, from: data)
print(response)
} catch {
print(error)
}
The above code is a straight-forward parsing of any number of nested levels. Any specific model architecture will depend upon how are you using the model.

Create a dictionary in swift with alamofire

Im trying to create a web request using alamofire in swift , by request object should be like this
{
"warranty": 0,
"descriptions": "string",
"product_name": "string",
"purchase_date": "23/10/2016",
"product_image": "string",
"product_receipt": "string",
"serial_number": "string",
"barcode_image": "string",
"serial_number_image": "string",
"product": {
"id": 1
},
"user": {
"id": 12
}
}
So in order to get this i have put my code as this
let parameters :[String:AnyObject] = [
"warranty":product.warrenty,
"descriptions":product.longDescription,
"product_name":product.initialName,
"purchase_date":product.purchaseDate,
"serial_number":product.serialCode,
"product": [
"id":product.id
],
"user": [
"id":userDefaults.getCustomerId()
]
]
But i when i do the request it seems that server doesn't accept this format , probably the way i assign
"product": {
"id": 1
},
"user": {
"id": 12
}
is not correct , what is the issue in here ? can some one point me the issue that i do here
I had the same issue and the problem was, i was missing the encoding option which you need to set .JSON. Match the below line with yours.
Alamofire.request(.POST, strURL, parameters: parameter as? [String : AnyObject], encoding: .JSON).responseJSON { (response: Response<AnyObject, NSError>) in

Why I cannot send multipartFormData with .POST parameters in Alamofire?

When I'm trying to send this:
Alamofire.upload(
.POST,
URL,
parameters: parameters,
multipartFormData: { multipartFormData in
it prints me the next error:
Type of expression is ambiguous without more context
I want to send my image file with the next parameters:
{
"user": {
"firstName": "ABC",
"email": null,
"birthDate": "1988-01-03",
"books": [{
"id": 1
}, {
"id": 2
}]
},
"locale": "en",
"sign": "It's me",
}
because of this structure, I cannot append it to multipart and I do not need send my parameters as a body of multipart, but as a parameters.
Is there any solutions for it?

How to create a dictionary with 2 arrays inside?

I want to create a dictionary with the next structure, for sending it via Alamofire as JSON to a server:
{
"user": {
"firstName": "fName",
"lastName": null,
"img": null,
"books": [
{
"id": 1
}, {
"id": 2
}
]
},
"locale": "en",
"gender": "male"
}
For this structure of JSON, I've tried the next:
let parameters: [[String: [String: String]], [String: String]]
but there a lot closures, so I confused with it. Can you help me with creating this structure?
The collection types in the Swift standard library only support homogenous collections, i.e. all elements in a collection must have the same type. So you cannot declare an array whose first element is of type [String: [String: String]] and whose second element is of type [String: String] if that is what you wanted.
This works:
let parameters = [
"user": [
"firstName": "fName",
"lastName": NSNull(),
"img": NSNull(),
"books": [
[ "id": 1],
[ "id": 2]
]
],
"locale": "en",
"gender": "male"
]
The type of parameters is [String: NSObject] where NSObject is the superclass of all the values in the dictionary. Note the use of NSNull to model null values, which is what NSJSONSerialization expects.

Resources