Send a [[String:AnyObject]] using SwiftyJSON - swift

I am requesting to an API using SwiftyJSON. I want to pass a value to a key which is in [[String: AnyObject]]:
var params = [String: AnyObject]()
parameters["paymentOptions"] = [["billingId": 1]]
So, directly passing it like this and making a request gave no response. So, I tried it like this:
var params = [String: AnyObject]()
parameters["paymentOptions"] = "\([["billingId": 1]])"
This gives an error from the API. I think I am doing something wrong here. How should I be sending the array?
This is how I make a request.
request(.POST, pathUrl, parameters: params)

Related

Swfit URLRequest POST How to make a request with duplicated parameter keys

I'm currently working on a project which uses Inoreader APIs, and there is one required post request with duplicated parameter keys.
https://www.inoreader.com/reader/api/0/edit-tag?a=user/-/state/com.google/read&i=12345678&i=12345679
As you can see duplicated i parameters. I've tried below to set httpBody of URLRequest, failed silently.
var parameters = [String: Any]()
parameters["i"] = idArray
parameters["a"] = "user/-/state/com.google/read"
let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [])
request.httpBody = jsonData
// I omitted other codes for simplicity
Then I've tried to chain every element of idArray with "&i=", assigned it to parameters["i"], also failed silently.
// chainedID was something like 123&i=456&i=789, to make it looks like as url example given by documentation
parameters["i"] = chainedID
How can I do that? This API is working perfectly with one item, but I can't get it work on multiple items. It claims will work with multiple items.
Based on the example that you posted and the ones that the documentation mentions, although the request is POST can accept parameters in the URL's query.
So, the solution would be to compose your request using URLComponents:
var components = URLComponents(string: "https://www.inoreader.com/reader/api/0/edit-tag")
var queryItems = [
URLQueryItem(name: "a", value: "user/-/state/com.google/read")
]
idArray.forEach {
queryItems.append(URLQueryItem(name: "i", value: $0))
}
components?.queryItems = queryItems
guard let url = components?.url else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
and not use JSON parameters in the request's body.

accessing data returned from socket in swift using socket.io

I've got the following to listen for new 'message' events with the use of Socket.IO
self.socket.on("message") {data, ack in
print("received data: \(data)")
// do stuff
}
Data I'm getting back in data looks as follows:
[{
conversationid = 1;
message = hello world;
senderid = 1;
}]
It's an array holding a single object but I'm struggling to access the individual elements in there. For example:
let message = ???
Many thanks!
Your data's type is [[String : Any]], if you wanna get the message try this:
Swift 5.x:
if let data = data as? [[String : Any]] {
let message = data[0]["message"] as? String ?? ""
print(message)
}
In this repo you have more info about how to implement socket.io
Played around with it a bit more.
The following works:
let socketResponse = data[0] as? NSDictionary
let message = socketResponse!["message"]
While that solution makes sense to me, it still doesn't make sense why e.g. the solution that #0x0010b suggested doesn't. That one seemed perfectly sound to me as well. Grateful for anyone input that can shed some light on this one ;-)

Send Core Data object to post api Alamofire multipartFormData

I have a screen on my app that I get some fields and save on my object Order. This object is my Core Data Object. After saving it, I need to send it to my backend through Alamofire POST multipartFormData.
The problem is that this is a Core Data Object (not Codable) and I need to send Data type on multipartFormData. How can I convert my object to Data? Is there another way of doing it?
What I've done:
let order = Order(context: DatabaseController.getContext())
order.orderItem = orderItem
order.product = product
order.value = value
order.date = date
Alamofire part:
Alamofire.upload (
multipartFormData: { multipartFormData in
multipartFormData.append(order, withName: "order")
},
to: url,
headers: headers,
encodingCompletion: { encodingResult in
The problem is how to put my object Order inside multipartFormData?
Could anyone help me please?
Updated:
Ok, sending the whole object didn't work, my api didn't accept, so I made a specific json only with the fields needed and turned it a Data type:
(PS: files are Data type from images user choose, even from camera or gallery)
var files = Dictionary<Data, String>()
var jsonFiles = [[String: String]]()
var jsonOrder = [String: Any]()
for file in files {
let dict : [String: String] = [ "orderImageIdLocal": uuidOrderImageIdLocal,
"orderItemAnalysisIdLocal": uuidAnalysisIdLocal,
"urlImageLocal": "\(imageId).jpg"]
jsonFiles.append(dict)
}
jsonOrder = [ "reason": "\(textViewReason)",
"orderImagess": jsonFiles,
"orderAnalysisId": "",
"orderIdLocal": "\(uuidAnaliseIdLocal)",
"orderId": "\(orderId ?? "")",
"typeSolicitation": "\(typeSolicitation)"]
Then I convert it to Data type like you said and send to Alamofire like above:
let orderData = try? JSONSerialization.data(withJSONObject: jsonOrder, options: .prettyPrinted) {
My problem now is that my api expect a zip file with those images user took from camera or gallery. So I am trying to use ZIPFoundation. I still don't know how to zip it and send. Should I zip each picture as Data type? Then transform zip file into Data type so I can send through multipartFormData.append?
I have tried: here and here
Here the code as an extension of NSManagedObject which creates dictionary from the attributes name.
extension NSManagedObject {
func toData() -> Data? {
let keys = Array(self.entity.attributesByName.keys)
let dict = self.dictionaryWithValues(forKeys: keys)
do {
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
return jsonData
}
catch{}
return nil
}
}
Usage:
let jsonData = order.toData()
multipartFormData.append(jsonData, withName: "order")

Swift - Adding data to a dictionary

So I have created a function which I use for all my requests, which will retry the request if fails and also add some of my headers to all requests for security.
The problem I am having is if data is nil, no values are being set in data.
Where am I going wrong here?
func performAndRetryRequestWithURL(method: Alamofire.Method, url: String, parameters: [String: AnyObject]?, completionHandler:(AnyObject?) -> Void) {
var data: [String: AnyObject]?
if (parameters != nil) {
data = parameters!
} else {
data = [String: AnyObject]?()
}
var unixTime = NSDate().timeIntervalSince1970
// I tried both ways to add timestamp
data?["timestamp"] = unixTime
data?.updateValue(unixTime, forKey: "timestamp")
data?.updateValue(hash("myfakekey"), forKey: "key")
println(data)
If parameters has data it seems to append, but if parameters is nil, data will be nil also.
Make data not optional:
var data = parameters ?? [String: AnyObject]()
If parameters is not nil, data will be assigned to parameter's unwrapped value. Otherwise, it will be initialized to an empty, non-optional dictionary.
The problem is in this line:
data = [String: AnyObject]?()
This looks at first glance like it should create an empty dictionary of type [String: AnyObject], but what it actually does is create an Optional dictionary that is initialized to nil. Get rid of the ? and it should work:
data = [String: AnyObject]()
Or, alternatively, since you've already identified data as being a dictionary of type [String: AnyObject]?, you could simply write:
data = [:]
That would create an empty dictionary as well.

How to make an HTTP GET Request with Parameters. SwiftyJSON Swift

Below mentioned snippet is working just fine. It queries JSON data. I just want to know how can I pass parameters with this.
let filePath = NSURL(string: "http://localhost:2403/postedjob")
let jsonData = NSData(contentsOfURL:filePath!)
let json = JSON(data: jsonData!, options: NSJSONReadingOptions.AllowFragments, error: nil)
I want to pass this parameters:
let params = ["$limit": 2, "$sort": ["id":"+1"]] as Dictionary<String, AnyObject>
Alamofire may be a good option for you to pass the parameters.
https://github.com/Alamofire/Alamofire
For a GET request pass parameters in the query string (the part after the "?" mark).
For a POST request parameters can be sent in the body in a number of ways. Raw data, form data and JSON among other methods.
Of course the server has to match the method used.