使用alamofire发送字典数组

时间:2015-01-06 08:38:06

标签: ios request alamofire

我必须通过POST请求发送字典数组。例如:

materials: [[String, String]] = [
  [
    "material_id": 1,
    "qty": 10
  ],
  [
    "material_id": 2,
    "qty": 5
  ]
]

Alamofire.request发送下一个帖子数据:

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
  ),
)

3 个答案:

答案 0 :(得分:6)

问题在于追加方法。我已经编写了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
}

答案 1 :(得分:2)

有几点想法:

  1. 如果您将响应作为带有一个键的字典发送,这将是最简单的,它将正确编码字典中的数组:

    let materials = [ "materials":
        [
            [
                "material_id": 1,
                "qty": 10
            ],
            [
                "material_id": 2,
                "qty": 5
            ]
        ]
    ]
    

    然后您可以将其作为parameters的{​​{1}}提供,Alamofire会为您正确编码。

  2. 如果您想发送一系列词典,另一种方法是将Web服务更改为接受JSON。然后,您可以自己编码JSON(使用request()JSONSerialization),设置请求的正文,然后发送该请求。

  3. 如果您想使用字典数组发送JSONEncoder请求,则必须自行编码。在Swift 3及更高版本中,这可能看起来像:

    application/x-www-form-urlencoded

    其中

    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 }() } 方法(例如responseresponse对比......)。

    无论如何,上面生成的请求正文如下:

    responseJSON

    这似乎是您在问题中要求的服务器解析的。

  4. 值得注意的是,最后一点说明了使用嵌套字典/数组结构准备materials[0][material_id]=1&materials[0][qty]=10&materials[1][material_id]=2&materials[1][qty]=5 请求,contemplated here。这可以在我的主服务器运行的服务器上运行,但我必须承认我没有看到正式RFC中记录的这个约定,所以我要小心这样做。我个人倾向于将其实现为JSON接口。

    对于Swift的早期版本,请参阅previous revision of this answer

答案 2 :(得分:0)

您可以将您的数组作为JSON字符串并发布到服务器,然后在服务器端解析JSON,然后从中获取所需的数据,请点击此处:

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: yourArry options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

希望这会有所帮助.. :)