使用 alamofire 发送字典数组
Sending array of dictionaries with alamofire
我必须通过 POST 请求发送字典数组。例如:
materials: [[String, String]] = [
[
"material_id": 1,
"qty": 10
],
[
"material_id": 2,
"qty": 5
]
]
Alamofire.request发送下一个post数据:
materials => array(
[0] => array("material_id" => 1),
[1] => array("qty" => 10),
[2] => array("material_id" => 2),
[3] => array("qty" => 5),
)
我想收到那个表示:
materials => array(
[0] => array(
"material_id" => 1,
"qty" => 10
),
[1] => array(
"material_id" => 2,
"qty" => 5
),
)
您可以将数组作为 JSON 字符串和 post 放入服务器,然后在服务器端解析 JSON 并从中获取所需的数据,如下所示:
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: yourArry options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
希望这对您有所帮助..:)
几个想法:
如果您使用一个键将响应作为字典发送,这将是最简单的,它会正确地编码字典中的数组:
let materials = [ "materials":
[
[
"material_id": 1,
"qty": 10
],
[
"material_id": 2,
"qty": 5
]
]
]
然后您可以将其作为 request()
的 parameters
提供,Alamofire 将为您正确编码。
如果您想发送一组字典,另一种方法是更改 Web 服务以接受 JSON。然后您可以自己对 JSON 进行编码(使用 JSONSerialization
或 JSONEncoder
),设置请求的主体,然后发送该请求。
如果你想用字典数组发送 application/x-www-form-urlencoded
请求,你必须自己编码。在 Swift 3 及更高版本中,它可能看起来像:
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)"
}
}
在哪里
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
}()
}
显然,使用任何适合服务器响应性质的 response
方法(例如 response
与 responseJSON
与 ...)。
无论如何,上面生成的请求正文如下所示:
materials[0][material_id]=1&materials[0][qty]=10&materials[1][material_id]=2&materials[1][qty]=5
这似乎已按照您在问题中的请求由服务器解析。
值得注意的是,最后一点说明了如何准备具有嵌套 dictionary/array 结构的 application/x-www-form-urlencoded
请求,如 contemplated here。这在我的服务器 运行 上由一家主要的 ISP 工作,但我必须承认我没有在正式的 RFC 中看到这个约定,所以我会小心翼翼地这样做。我个人倾向于将其实现为 JSON 接口。
有关 Swift 的早期版本,请参阅 previous revision of this answer。
问题出在附加方法中。我已经编码了 PHP 5 年并且忘记了 Swift 中的索引不会像 PHP 中那样自动分配。所以,我的第一个错误代码是:
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
}
答案是根据需要硬分配键:
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
}
我必须通过 POST 请求发送字典数组。例如:
materials: [[String, String]] = [
[
"material_id": 1,
"qty": 10
],
[
"material_id": 2,
"qty": 5
]
]
Alamofire.request发送下一个post数据:
materials => array(
[0] => array("material_id" => 1),
[1] => array("qty" => 10),
[2] => array("material_id" => 2),
[3] => array("qty" => 5),
)
我想收到那个表示:
materials => array(
[0] => array(
"material_id" => 1,
"qty" => 10
),
[1] => array(
"material_id" => 2,
"qty" => 5
),
)
您可以将数组作为 JSON 字符串和 post 放入服务器,然后在服务器端解析 JSON 并从中获取所需的数据,如下所示:
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: yourArry options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
希望这对您有所帮助..:)
几个想法:
如果您使用一个键将响应作为字典发送,这将是最简单的,它会正确地编码字典中的数组:
let materials = [ "materials": [ [ "material_id": 1, "qty": 10 ], [ "material_id": 2, "qty": 5 ] ] ]
然后您可以将其作为
request()
的parameters
提供,Alamofire 将为您正确编码。如果您想发送一组字典,另一种方法是更改 Web 服务以接受 JSON。然后您可以自己对 JSON 进行编码(使用
JSONSerialization
或JSONEncoder
),设置请求的主体,然后发送该请求。如果你想用字典数组发送
application/x-www-form-urlencoded
请求,你必须自己编码。在 Swift 3 及更高版本中,它可能看起来像: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)" } }
在哪里
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 }() }
显然,使用任何适合服务器响应性质的
response
方法(例如response
与responseJSON
与 ...)。无论如何,上面生成的请求正文如下所示:
materials[0][material_id]=1&materials[0][qty]=10&materials[1][material_id]=2&materials[1][qty]=5
这似乎已按照您在问题中的请求由服务器解析。
值得注意的是,最后一点说明了如何准备具有嵌套 dictionary/array 结构的 application/x-www-form-urlencoded
请求,如 contemplated here。这在我的服务器 运行 上由一家主要的 ISP 工作,但我必须承认我没有在正式的 RFC 中看到这个约定,所以我会小心翼翼地这样做。我个人倾向于将其实现为 JSON 接口。
有关 Swift 的早期版本,请参阅 previous revision of this answer。
问题出在附加方法中。我已经编码了 PHP 5 年并且忘记了 Swift 中的索引不会像 PHP 中那样自动分配。所以,我的第一个错误代码是:
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
}
答案是根据需要硬分配键:
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
}