POST multiple json objects in Alamofire POST method - Swift/IOS - ios

Sorry if my question is not clear, I'll try to make myself clear with an explanation. So here is exactly what I'm trying to do, I'm trying to use Alamofire to post more than one comment (Something that my app implements and will be stored as a JSON object whenever user writes a new comment). I'm passing these JSON comments to my post routine, where I can use SwiftyJSON to extract each value. Noe the thing is I know how to set the parameters if I'm trying to authorize the user as follows,
var parameters = [
"userName": userName,
"password": passwordSalt,
"somethingElse": somethingElse
]
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters , options: nil, error: &err)
it's quite straightforward until here, now comes my problem. I'm trying to use alamofire post to post multiple json objects, which should look like this
[
{
"comment": "my First Comment",
"commentDate": "2014-05-13 14:30 PM",
"isSigned": 1,
"patientId": 2,
"documentId": 3
},
{
"comment": "my SecondComment",
"commentDate": "2014-05-14 14:30 PM",
"isSigned": 2,
"patientId": 3,
"documentId": 4
},
{
"comment": "my third Comment",
"commentDate": "2014-05-15 14:30 PM",
"isSigned": 3,
"patientId": 4,
"documentId": 5
}
]
How do I create above array/json (I'm not exactly sure on what to call this) by iterating JSON object? I know how to get the JSON values from the JSON object all I'm asking is how to create this parameters variable to hold the data like above example. Is it even possible to do this using Alamofire? (POST multiple objects at once)
I tried a couple of ways to but they didn't work out
var dictArray = [Dictionary<String, Any>]
var dict = Dictionary<String, Any>
While iterating over JSON object inserted each value in dict and appended dict to dictArray, now when I'm trying to use dictArray as parameters in .dataWithJSONObject it doesn't like the object.
var dict = Dictionary<String, AnyObject>
var array = NSArray()
extracted each value by iterating over the JSON object and inserted them into dict and tried inserting dict into array. But this gives a different problem. The way it builds the objects is different from what is required, as follows.
[
{
comment: my First Comment,
commentDate: 2015-05-13 13:30 PM"",
isSigned: 1,
patientId: 2,
documentId: 3
},
{
comment: my Second Comment,
commentDate: 2015-05-13 13:30 PM"",
isSigned: 2,
patientId: 5,
documentId: 4
},
{
comment: my third Comment,
commentDate: 2015-06-13 13:30 PM"",
isSigned: 5,
patientId: 1,
documentId: 9
}
]
Here the Keys doesn't get wrapped inside quotes (Correct way: "comment", wrong way: comment).
Did anyone try posting multiple objects, is alamofire capable of doing so? I hope I made the question clear. Sorry if this is too simple of a question to answer, I spent my whole day figuring this out but didn't work out.

The correct representation in Swift for the array of comment objects you have posted would be like this:
let comments: Array<[String:AnyObject]> = [
[
"comment": "my First Comment",
"commentDate": "2014-05-13 14:30 PM",
"isSigned": 1,
"patientId": 2,
"documentId": 3
],
[
"comment": "my SecondComment",
"commentDate": "2014-05-14 14:30 PM",
"isSigned": 2,
"patientId": 3,
"documentId": 4
],
[
"comment": "my third Comment",
"commentDate": "2014-05-15 14:30 PM",
"isSigned": 3,
"patientId": 4,
"documentId": 5
]
]
Sending a single comment would be fairly simple:
let comment: [String:AnyObject] = [
"comment": "my First Comment",
"commentDate": "2014-05-13 14:30 PM",
"isSigned": 1,
"patientId": 2,
"documentId": 3
]
Alamofire.request(.POST, "http://httpbin.org/post", parameters: comment).responseJSON { (req, res, json, error) in
println(req)
println(res)
println(json)
println(error)
}
However, in order to send an array of comments, seems like you would have to generate the URLRequest your self and then pass it to Alamofire as follows:
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: "http://httpbin.org/post")!)
mutableURLRequest.HTTPMethod = "POST"
var error: NSError? = nil
let options = NSJSONWritingOptions.allZeros
if let data = NSJSONSerialization.dataWithJSONObject(comments, options: options, error: &error) {
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
mutableURLRequest.HTTPBody = data
}
Alamofire.request(mutableURLRequest).responseJSON { (req, res, json, error) in
println(req)
println(res)
println(json)
println(error)
}
If you could modify the API backend to accept an object with multiple comments, you could also send them this way:
Alamofire.request(.POST, "http://httpbin.org/post", parameters: ["comments": comments]).responseJSON { (req, res, json, error) in
println(req)
println(res)
println(json)
println(error)
}
Regards.

This would be better
Create dictionary and array of dictionary var
Then loop how many parameters you need to send from data source either an array or whatever.
Here my scenario
Need to answer to all questions (will be a random number/size)
var ansParams = [[String: String]]()
var paramz = [String: String]()
for question in sectionQuestions{
paramz = [
AppConstants.PARAMETER.KEY_1 : "Value",
AppConstants.PARAMETER.KEY_2 : "Value",
AppConstants.PARAMETER.KEY_3 : "Value",
AppConstants.PARAMETER.KEY_4 : "Value",
AppConstants.PARAMETER.KEY_5 : "Value"
]
ansParams.append(paramz)
}
print(ansParams)
//Check All Paramz and its values then send ansParams as Parameter to POST request

I had a similar issue in my project while working with an API that did now allow posting multiple objects at once. The formatting of the array as noted above is fine.
let comments: Array<[String:AnyObject]> = [
[
"comment": "my First Comment",
"commentDate": "2014-05-13 14:30 PM",
"isSigned": 1,
"patientId": 2,
"documentId": 3
],
[
"comment": "my SecondComment",
"commentDate": "2014-05-14 14:30 PM",
"isSigned": 2,
"patientId": 3,
"documentId": 4
],
[
"comment": "my third Comment",
"commentDate": "2014-05-15 14:30 PM",
"isSigned": 3,
"patientId": 4,
"documentId": 5
]
]
Then I used a for loop to post each object of the array to post the API.
var index = comments.count
var i = 0
for i = 0; i < index; i++ {
let urlString = "\(.baseURL)...etc"
let parameters = comments[i]
Alamofire.request(.POST, urlString, parameters: parameters)
.responseJSON { (req, res, data, error) -> Void in
// println(req)
// println(res)
// println(data)
// println(error)
println("\(i) of \(index) posted")
}
}
More efficient ways if the API allows, but otherwise this flow works great.

Related

JSONDecoder can't decode Array but can decode String

I have a struct that I would like to parse from Json:
struct Subsidiary: Decodable {
let id: Int?
let subsidiary_ref: String?
let name: String?
let address: String?
}
I try to parse it like:
let sub: [Subsidiary] = try! JSONDecoder().decode([Subsidiary].self, from: data)
where data is Data type from
session.dataTask(with: urlRequest) { (data, response, error) in
and it gives me an error
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a string/data instead.", underlyingError: nil))
If I do it like this:
let sub: String = try! JSONDecoder().decode(String.self, from: data)
it works and it gives me son
[
{"id": 5913, "subsidiary_ref": "0000159", "name": "Mercator Hipermarket Koper", "address": "Poslov.98-Koper,Dolinska C", "city": "Koper", "coordinates_x": null, "coordinates_y": null, "phone_number": "+386 56-636-800", "frequency": "A", "channel": "Food", "subchannel": "Hypermarket", "customer": 7, "day_planned": true, "badge_visible": true, "open_call": true, "number_of_planned": 13, "number_of_calls": 22, "last_call_day": 3, "notes": " notesi ki ne smejo nikoli zginiti bla marko bdsa"},
{"id": 5870, "subsidiary_ref": "0000773", "name": "Kompas Shop Pe Ferneti?i", "address": "Partizanska 150", "city": "Se?ana", "coordinates_x": null, "coordinates_y": null, "phone_number": "+386 57-380-636", "frequency": "A", "channel": "Food", "subchannel": "Supermarket", "customer": 17, "day_planned": true, "badge_visible": true, "open_call": true, "number_of_planned": 13, "number_of_calls": 1, "last_call_day": 1, "notes": null},...
]
What is wrong with my code?
EDIT:
I figure out, that if I create a string variable, and then convert this string value to data it works even with Subsidiary struct.
So something should be wrong with the data variable.
The fact that you can decode a String.self and get your JSON printed means that the root of the JSON is a string. The JSON you got, in text form, probably looks like this:
"[\r\n {\"id\": 5913, \"subsidiary_ref\": \"0000159\", \"name\": \"Mercator Hipermarket Koper\", \"address\": \"Poslov.98-Koper,Dolinska C\", \"city\": \"Koper\", \"coordinates_x\": null, \"coordinates_y\": null, \"phone_number\": \"+386 56-636-800\", \"frequency\": \"A\", \"channel\": \"Food\", \"subchannel\": \"Hypermarket\", \"customer\": 7, \"day_planned\": true, \"badge_visible\": true, \"open_call\": true, \"number_of_planned\": 13, \"number_of_calls\": 22, \"last_call_day\": 3, \"notes\": \" notesi ki ne smejo nikoli zginiti bla marko bdsa\"}\r\n]"
Note that the actual JSON you want is put in ""s, so all the special characters are escaped.
The web service has given the JSON in a very weird way...
To get the actual JSON data decoded, you need to get the string first, then turn the string into Data, then decode that Data again:
// nil handling omitted for brevity
let jsonString = try! JSONDecoder().decode(String.self, from: data)
let jsonData = jsonString.data(using: .utf8)!
let sub = try! JSONDecoder().decode([Subsidiary].self, from: jsonData)
Of course, the best solution is to fix the backend.

How to consume an API response with Swift

I am trying to make an API request to get an API response I am getting all the elements but I am facing braces issue I want a whole response and "order_devices" key, in {} braces but I am getting these in [] braces.
the array in which i am passing value,
var popUpArray :[[String:AnyObject]] = []
then on btn click i am saving values in dictionary
#IBAction func btnSave(_ sender: Any) {
let popupDict = (["quantity": Int(txtEnterQuantity.text!), "name": lblDeviceName.text,"id": deviceDict["id"], "region":1, "system_integrated":1 ])as! [String:AnyObject]
and then passing the same dictionary value as parameter
let passDict = [
"dealer_id":dropDownId!,
"client_id":dropDownId!,
"distributor_id":searchBarId!,
"emp_id":UserId,
"comments":CommentKey!,
"accepted_by":0,
"valid_from":strDate!,
"valid_upto": 0,
"order_devices":popupDict
] as [String : Any]
if Reachability.isConnectedToNetwork() {
showActivityIndicator()
Alamofire.request("http://13.232.230.41/IAC_CRM/public/api/createOrder", method: .post, parameters: passDict, encoding: JSONEncoding.default, headers: [:])
.responseJSON { (response) in
i am getting this response ,
[
"comments": "demo",
"dealer_id": 3,
"valid_from": "6-3-2019",
"distributor_id": 72,
"client_id": 3,
"accepted_by": 0,
"emp_id": 33,
"valid_upto": 0
"order_devices":
[
[
"id": 1,
"quantity": 10,
"region": 1,
"system_integrated": 1
]
,
[
"id": 2,
"quantity": 12,
"region": 1,
"system_integrated": 1
]
]
]
i want this response,
{ "dealer_id":"1", "client_id":"2", "distributor_id":"2",
"emp_id":"1", "comments":"IAC test device comments", "accepted_by":0,
"valid_from":"2019-01-24", "valid_upto":"1", "order_devices":[
{
"device_id":"1",
"quantity":"1", "region":1, "system_integrated":1
}
,
{
"device_id":"2",
"quantity":"1"
"region":1,
"system_integrated":1
}
] }
means i want whole response and "order_devices" key in "curly braces"{} .
There is nothing wrong with request or response, your are getting response what your API is returning, You should ask you backend developer Or Api Provider to Give you response in form of your requirement i mean proper formatted Right now its in form of Array.

Posting complex array with Alamofire

I have a problem with posting complex dynamic array with Alamofire to my REST API. I would like to post something like this;
let parameters = [
"A": "a",
"B": myObject.getStringValue(),
"C": myDate.timeIntervalSince1970,
"D": myObject2.getStringValue(),
"E": MyComplexData
];
Alamofire.request(.POST, "http://myrestapi.com/myaction", parameters: parameters);
Where the myComplexData is an array-like variable, which I would like to fill with a loop. I want receive data in the server like this:
[
"A": "a",
"B": "b",
"C": 24916942128,
"D": "d",
"E": [0: [ id: "firstID", value: "firstValue" ], 1: [ id: "secondID", value: "secondValue" ]]
]
My question is, how can I create a dynamic array (or dictionary?) into the MyComplexData to receive data like this?
Thanks in advance,
Robert
Finally, based on #Catalina T. answer, I did it with JSON encoded data. The full code:
var myComplexData = Dictionary<String, String>();
for i in previousCollectedDynamicDataArray {
myComplexData[i.getID()] = i.getVal();
}
let parameters = [
"A":"A",
"B": myObject.getStringValue(),
"C": myDate.timeIntervalSince1970,
"D": myObject2.getStringValue(),
"E": myComplexData
];
Alamofire.request(.POST, "http://myrestapi.com/myaction", parameters: [ "data": objToJSONString(parameters) ]);
And this is the objToJSONString function:
func objToJSONString(obj: AnyObject) -> String {
guard let data = try? NSJSONSerialization.dataWithJSONObject(obj, options: .PrettyPrinted),
let jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
else {
return "";
}
return jsonString as String;
}
And the server received the "data" post variable the JSON encoded data inside.

Turn an array into a escaped string

I have an array of dictionaries like this one.
[["updated_at": , "expected_qty": 1, "parts_id": 1, "mappingType": service, "description": , "name": Epoxy, "created_at": , "price": 0, "win_service_id": 1, "id": 1, "mappingID": 1], ["updated_at": , "expected_qty": 1, "parts_id": 2, "mappingType": service, "description": , "name": Wood for Lami, "created_at": , "price": 0, "win_service_id": 1, "id": 2, "mappingID": 1]]
I need to make this entire array into an escaped string. Something like this.
"[{\"updated_at\":\"\",\"expected_qty\":1,\"parts_id\":1,\"mappingType\":\"service\",\"description\":\"\",\"name\":\"Epoxy\",\"created_at\":\"\",\"price\":0,\"win_service_id\":1,\"id\":1,\"mappingID\":1},{\"updated_at\":\"\",\"expected_qty\":1,\"parts_id\":2,\"mappingType\":\"service\",\"description\":\"\",\"name\":\"Wood for Lami\",\"created_at\":\"\",\"price\":0,\"win_service_id\":1,\"id\":2,\"mappingID\":1}]"
I know you can convert an array to a string using array.description but I don't know how to escape those characters within it. I searched a lot but I couldn't find a method that does this either.
I tried adding a string extension to do something like this.
extension String {
var escaped: String {
return self.stringByReplacingOccurrencesOfString("\"", withString: "\\\"")
}
}
The result is this.
[[\"updated_at\": , \"expected_qty\": 1, \"parts_id\": 3, \"mappingType\": service, \"description\": , \"name\": Sill, \"created_at\": , \"price\": 0, \"win_service_id\": 8, \"id\": 3, \"mappingID\": 8]]
It looks like it's almost the expected output but notice the inner pairs of square brackets. Those must be the curly brackets.
So is there a better way to do this?
You can convert your dictionary into json using NSJSONSerialization. Try the following code out
let dict = ["key":"value","key1":"0","key2":"1"] as Dictionary<String, AnyObject>
let data = try? NSJSONSerialization.dataWithJSONObject(dict, options:NSJSONWritingOptions.PrettyPrinted)
var datastring = String(data: data!, encoding: NSUTF8StringEncoding)

IOS: Swift: Append String to a file

i have file inside document directory and i want to add some text (it'l be a string in JSON format) to this file. As of now i'm using below line of code to write to the file but it is overriding the file every time i write to it. So is there a better way to handle this situation ? i'm new to swift and can't seem to find a solution.
stringVariable.writeToFile(self.directoryPath, atomically: false, encoding: NSUTF8StringEncoding, error: nil)
As it is going to be a file with JSON String's in it, how to check if the text already has some data and assign or remove "," (Comma) from the end of the Json String?
Initially the file contains some text like
{ "documentComments":[]}
My JSON String is like as follows,
{ "comment": "MySecondComment", "commentDate": "2015-04-23 17:58:59 +0000", "isSigned": 1, "accountId": 1, "documentId": 3 }
By inserting couple of json string i want the file to finally look like below,
{ "documentComments":[
{ "comment": "MyFirstComment", "commentDate": "2015-04-22 17:58:59 +0000", "isSigned": 0, "accountId": 1, "documentId": 2 },
{ "comment": "MySecondComment", "commentDate": "2015-04-23 17:58:59 +0000", "isSigned": 1, "accountId": 1, "documentId": 3 }]}
Thanks in Advance

Resources