I'm trying to make a put request with Alamofire and I want to pass in body something like this:
[
{
"id" : 1,
"position": 0
},
{
"id" : 2,
"position": 1
},
{
"id" : 6,
"position": 2
}
]
Normally, to do a request with alamofire I do this:
request = Alamofire
.request(
url,
method: method,
parameters: parameters,
encoding: encoding,
headers: buildHeaders());
Alamofire forces me to make parameters a dictionary but I want that paramaters to be an array of dictonary. How can I do this?
Thanks.
Alamofire added support for Encodable parameters in Alamofire 5, which provides support for Array parameters. Updating to that version will let you use Array parameters directly. This support should be automatic when passing Array parameters, you just need to make sure to use the version of request using encoder rather than encoding if you're customizing the encoding.
Well, the body of your parameters has type as [[String: Any]], or if you using Alamofire [Parameters].
So you if you parsing some Array of Objects to create this Array of parameters. You can do like this:
var positionedArray = [[String : Any]]()
for (index, item) in dataArray.enumerated() {
guard let id = item.id else {
return
}
let singleParameters : [String: Any] = ["id": id, "position" : index]
sorted.append(singleParameters)
}
As result, you can use this body (parameters), for your request.
Also, you should use JSONSerialization:
For example, if you using a customized Alamofire client, just use extension:
let data = try JSONSerialization.data(withJSONObject: parameters, options: JSONSerialization.WritingOptions.prettyPrinted)
let json = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
request.httpBody = json!.data(using: String.Encoding.utf8.rawValue)
var finalRequest = try URLEncoding.default.encode(request, with: nil)
Related
I have tried many solution many times but any them not worked. finally if some one could help that would be really help. I will help you with the link and format of data need to be passed. You can check how postman to insert code and the below code which I tried. Thanks in advance!
This below way I insert data by postman :
insert : 0
Data : [{"user_id":"46","e_id":"566","date_list":"2018/04/25","t_depo":" 0.0","mini":"20","real_earn":"-5000.0","mb_balance":"-4000.0","balance_for":"4000"}]
The below code way I tried and I just get response updated successfully but no change in database when I check by postman
var dict = [String : String]()
dict["user_id"] = "46"
dict["e_id"] = "566"
dict["date_list"] = "2018/04/25"
dict["t_depo"] = " 0.0"
dict["mini"] = "200"
dict["real_earn"] = "-5000"
dict["mb_balance"] = "4000"
dict["balance_for"] = "4000"
var dictArray = [dict];
let parameter: Parameters = [
"insert" : "0",
"Data" : dictArray
]
Alamofire.request("url", method: .post, parameters: parameter, encoding: JSONEncoding.default)
.responseJSON {(response) in
print(parameter)
}
}
Seems that your "insert" is of type int and you're using a type string. Try with
let parameter: Parameters = [
"insert" : 0,
"Data" : dictArray
]
I would also check the response object. I believe you should get a status code 201 "Created"
i'm try to post a JSON using Swift3 and Alamofire and it work successfully in Postman Postman screen shot
but in code the response is HTML string that means an exception in server
i tried to change encoding from JsonEncoding.default to URLEncoding.default and it works good but after 3 days the same error when i run the app
let url = "http://mattam.net/mobileapp/addOrder"
let par:[String:Any] = ["order_restaurant":8,
"order_type":1,
"order_address":1,
"order_within":"45 mins",
"order_exacttime":"09:00 pm",
"order_total":300,
"order_fees":30,
"order_gtotal":330,
"order_user":38,
"pquantity[10]":3,
"pquantity[9]":1,
"poption[9]":238,
"pextra[10]":"80,81"]
print(par)
Alamofire.request(url, method: .post, parameters: par, encoding: URLEncoding.default).responseJSON{
r in
if r.result.isSuccess{print("------i______i-----")}
print(r)
if let result = r.result.value as? NSDictionary{
print(result)}
}
and in PostMan Bulk edit is
order_restaurant:8
order_type:1
order_address:1
order_within:45 mins
order_exacttime:09:00 pm
order_total:300
order_fees:30
order_gtotal:330
order_user:38
pquantity[10]:3
pquantity[9]:1
poption[9]:238
pextra[10]:80,81
and url is "let url = "http://mattam.net/mobileapp/addOrder""
Your problem is that your using http instead of https in your app.
The screenshot uses https while the url you posted (copied from your code) uses http.
If I understand your question right, you need to send some post details to the server as a Json, so here is some code to do that:
private func alamoFireAjax(url: String, parameters: Parameters, callback: #escaping (DataResponse<Any>) -> Void) {
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON(completionHandler: callback)
}
I had a similar issue and to solve it I placed the dictionary creation in a method call. You can usually get away with most requests but I found anything larger than 10 rows needed a separate method handler.
fileprivate func generateParams() -> [String: Any] {
var params = [String: Any]()
params["order_restaurant"] = 8
params["order_type"] = 1
params["order_address"] = 1
params["order_within"] = "45 mins"
params["order_exacttime"] = "09:00 pm"
params["order_total"] = 300
params["order_fees"] = 30
params["order_gtotal"] = 330
params["order_user"] = 38
params["pquantity[10]"] = 3
params["pquantity[9]"] = 1
params["poption[9]"] = 238
params["pextra[10]"] = "80,81"
return params
}
i am trying to send dictionary data using POST method dataTaskWithRequest() can send this only in string URL format.
How can we convert dictionary data into HTTP URL format?
Here is an example:
let parameters = [
"first": "name",
"second": ["a", "b"],
"third": [
"x": 1,
"y": 2,
"z": 3
]
]
convert it into
first=name&second[]=a&second[]=b&third[x]=1&third[y]=2&third[z]=3
using swift 2.3
You can convert your dictionary to json using this code and set HTTPBody
let jsondata = NSJSONSerialization.dataWithJSONObject(parameters, options: .PrettyPrinted)
request.HTTPBody = jsondata
Faced the same issue. Converted the Dictionary using below code :
let postString = (dictionaryParameters.flatMap({ (key, value) -> String in
return "\(key)=\(value)"
}) as Array).joined(separator: "&")
and attached the string in httpBody of the request :
request.httpBody = postString.data(using: String.Encoding.utf8)
got the response finally.
Got help from this link:
Convert Swift Dictionary to String
I have to send array of dictionaries via POST request. For example:
materials: [[String, String]] = [
[
"material_id": 1,
"qty": 10
],
[
"material_id": 2,
"qty": 5
]
]
Alamofire.request sends the next post data:
materials => array(
[0] => array("material_id" => 1),
[1] => array("qty" => 10),
[2] => array("material_id" => 2),
[3] => array("qty" => 5),
)
I want receive that representation:
materials => array(
[0] => array(
"material_id" => 1,
"qty" => 10
),
[1] => array(
"material_id" => 2,
"qty" => 5
),
)
The problem was in append method. I have coded on PHP 5 years and forgoted that in Swift the indexes not automatically assigned like in PHP. So, my first bugged code was:
func getParameters() -> [[String: AnyObject]] {
var result = [[String: AnyObject]]()
for mmap in mmaps {
let material: [String: AnyObject] = [
"material_id": mmap.material.id,
"quantity": mmap.qty
]
result.append(material)
}
return result
}
The answer is hard assign the keys as you need:
func getParameters() -> [String: [String: AnyObject]] {
var result = [String: [String: AnyObject]]()
let mmaps = self.mmaps.allObjects as [Mmap]
for i in 0..<mmaps.count {
let mmap = mmaps[i]
let material: [String: AnyObject] = [
"material_id": mmap.material.id,
"quantity": mmap.qty
]
result["\(i)"] = material
}
return result
}
A couple of thoughts:
It would be easiest if you sent the response as a dictionary with one key, and it will correctly encode the array within the dictionary:
let materials = [ "materials":
[
[
"material_id": 1,
"qty": 10
],
[
"material_id": 2,
"qty": 5
]
]
]
You could then just supply that as the parameters of request(), and Alamofire will properly encode that for you.
If you wanted to send an array of dictionaries, an alternative would be to change the web service to accept JSON. You could then encode the JSON yourself (using JSONSerialization or JSONEncoder), set the body of the request, and then send that request.
If you want to send application/x-www-form-urlencoded request with the array of dictionaries, you'd have to encode that yourself. In Swift 3 and later, that might look like:
func encodeParameters(_ object: Any, prefix: String? = nil) -> String {
if let dictionary = object as? [String: Any] {
return dictionary.map { key, value -> String in
self.encodeParameters(value, prefix: prefix != nil ? "\(prefix!)[\(key)]" : key)
}.joined(separator: "&")
} else if let array = object as? [Any] {
return array.enumerated().map { (index, value) -> String in
return self.encodeParameters(value, prefix: prefix != nil ? "\(prefix!)[\(index)]" : "\(index)")
}.joined(separator: "&")
} else {
let escapedValue = "\(object)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
return prefix != nil ? "\(prefix!)=\(escapedValue)" : "\(escapedValue)"
}
}
Where
extension CharacterSet {
/// Returns the character set for characters allowed in the individual parameters within a query URL component.
///
/// The query component of a URL is the component immediately following a question mark (?).
/// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query
/// component is `key1=value1`. The individual parameters of that query would be the key `key1`
/// and its associated value `value1`.
///
/// According to RFC 3986, the set of unreserved characters includes
///
/// `ALPHA / DIGIT / "-" / "." / "_" / "~"`
///
/// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters
/// for the sake of compatibility with some erroneous implementations, so this routine also allows those
/// to pass unescaped.
static var urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
return allowed
}()
}
Obviously, use whatever response method is appropriate for the nature of your server's response (e.g. response vs. responseJSON vs. ...).
Anyway, the above generates a request body that looks like:
materials[0][material_id]=1&materials[0][qty]=10&materials[1][material_id]=2&materials[1][qty]=5
And this appears to be parsed by servers as you requested in your question.
It's worth noting that this final point illustrates the preparation of an application/x-www-form-urlencoded request with nested dictionary/array structure, as contemplated here. This works on my server run by a major ISP, but I must confess that I haven't seen this convention documented in formal RFCs, so I'd be wary of doing it. I'd personally be inclined to implement this as JSON interface.
For prior versions of Swift, see previous revision of this answer.
You can make your array as JSON string and post in to server, then parse JSON in server end and from that you can get your desired data, lke this:
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: yourArry options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
Hope this helps.. :)
I am new to SwiftyJSON, and I'm having some trouble with it. I can get it to return the entire JSON file as a string, but the moment I try to parse it, I keep getting empty variables back, and I'm not sure what I'm doing wrong.
This is the formatting of my JSON file:
[
{
"entryID": 1,
"from": "String",
"to": "String",
"value": "String"
},
{
...
},
...
]
And this is roughly what I want to do with it (in quite inelegant code, I do apologise, I'm new to Swift):
for entry: JSON in indexJSON.arrayValue {
var vEntryID: Int
var vFrom: String
var vTo: String
var vValue: String
for (dictKey: String, dictVal: JSON) in entry.dictionaryValue {
if(dictKey=="entryID") {vEntryID = dictVal.intValue}
if(dictKey=="from") {vFrom = dictVal.stringValue}
if(dictKey=="to") {vTo = dictVal.stringValue}
if(dictKey=="value") {vValue = dictVal.stringValue}
}
someSwiftObject[vEntryID]["from"] = vFrom
someSwiftObject[vEntryID]["to"] = vTo
someSwiftObject[vEntryID]["value"] = vValue
}
However, this block never executes at all, because indexJSON.arrayValue is always empty.
When I try to run the following, it correctly prints the complete file contents to the console:
let indexJSON = JSON(content!)
println(indexJSON.stringValue)
But when I try to go deeper, to fetch any element, it returns nothing:
if(indexJSON.arrayValue.isEmpty==true) {println("indexJSON.arrayValue is Empty")}
if(indexJSON[0].arrayValue.isEmpty==true) {println("indexJSON[0].arrayValue is Empty")}
if(indexJSON[0].dictionaryValue.isEmpty==true) {println("indexJSON[0].dictionaryValue is Empty")}
if(indexJSON[0]["entryID"]==nil) {println("indexJSON[0][\"entryID\"].stringValue is Empty")}
Output:
indexJSON.arrayValue is Empty
indexJSON[0].arrayValue is Empty
indexJSON[0].dictionaryValue is Empty
indexJSON[0]["entryID"].stringValue is Empty
I'd be grateful for any help! What am I doing wrong?
I checked SwiftyJSON source code and I think I know where the problem is.
I suppose that you are using String to initialize the JSON object like this
let s = "{\"entryID\": 1,\"from\": \"String\",\"to\": \"String\",\"value\": \"String\"}"
let j = JSON(s)
In this case the JSON object is actuall given a type "String", not Array. That's why it's not iterable and its arrayValue is empty.
To do what you want to do, you need to initialize it with an Array object:
let arr = [
[
"entryID":1,
"from":"String",
"to":"String",
"value":"String",
]
]
let j2 = JSON(arr)
Now j2 is an array JSON object and iterable.
SwiftyJSON can only be initialized with NSData and object. So if you want to initialize it with a String you need to do this:
if let data = s.dataUsingEncoding(NSUTF8StringEncoding) {
let j = JSON(data:data)
println(j)
}
first of all, make sure the format of your json string is correct. in your question, your json string is a array, just format the string like this(the content is from my code):
let jsonStr = "[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 1,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
then you can use SwityJson to get the array object, like this:
let strData = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false)
let json = JSON(data: strData!)
for object in json.arrayValue {
let name = object["name"].string
}
Take a look at the documentation here: https://github.com/lingoer/SwiftyJSON#loop
You are iterating it incorrectly. You should be iterating over the array with a for loop like this:
for (index: String, subJson: JSON) in json {
//Do something you want
}