如何修复Alamofire传参时的‘字典字面量包含重复键’错误?
解决Alamofire请求中重复键参数的传递问题
Hey,我之前对接SOAP API的时候也碰到过一模一样的问题——Swift的Dictionary本身就不允许存在重复键,所以你直接用[String: Any]定义参数肯定会触发Dictionary literal contains duplicate keys错误。针对你的场景,这里有几个实用的解决方案:
方案1:手动构建HTTP请求体(最适配SOAP场景)
SOAP请求本质是基于HTTP的结构化请求(不管是XML还是JSON格式),我们可以绕过Swift字典的限制,直接拼接符合后端要求的JSON字符串作为请求体,这样就能完美保留重复键了。
具体步骤如下:
- 先写出符合要求的JSON模板,把动态变量用占位符替换
- 将动态变量(比如邮箱、航班数据等)转成字符串后替换到模板中
- 把最终的JSON字符串转成
Data,直接设置为Alamofire请求的httpBody
代码示例:
// 先将字典/数组类型的动态数据转成JSON字符串 var flight1JsonStr = "" if let data = try? JSONSerialization.data(withJSONObject: selectedflightjson, options: []), let str = String(data: data, encoding: .utf8) { flight1JsonStr = str } var flight1RmJsonStr = "" if let data = try? JSONSerialization.data(withJSONObject: selectedflightjsonRM, options: []), let str = String(data: data, encoding: .utf8) { flight1RmJsonStr = str } var passengersJsonStr = "" if let data = try? JSONSerialization.data(withJSONObject: passengerparameterarray, options: []), let str = String(data: data, encoding: .utf8) { passengersJsonStr = str } // 拼接完整的JSON请求体字符串 let requestBodyStr = """ { "contactPerson": { "email": { "email": "\(contactemail)", "markedForSendingRezInfo": false, "preferred": false, "shareMarketInd": false }, "personName": { "givenName": "\(contactname)", "shareMarketInd": false, "surname": "\(contactlastname)" }, "phoneNumber": { "countryCode": "\(contactcountrycode)", "markedForSendingRezInfo": false, "preferred": false, "shareMarketInd": false, "subscriberNumber": "\(contactphone)" }, "shareMarketInd": false, "useForInvoicing": false }, "curr":"USD", "flight1" : \(flight1JsonStr), "flight1" : \(flight1RmJsonStr), "passengers": \(passengersJsonStr), "pwd": "\(password)", "requestPurpose": "MODIFY_PERMANENTLY_AND_CALC", "unm": "\(username)" } """ // 转成Data后传给Alamofire if let requestBodyData = requestBodyStr.data(using: .utf8) { AF.request(yourApiUrl, method: .post, headers: yourRequestHeaders) .httpBody(requestBodyData) .responseJSON { response in // 处理你的响应逻辑 } }
方案2:将重复键转为数组(需后端支持)
如果后端SOAP服务允许把重复键的参数转换成数组格式(比如把"flight1": val1, "flight1": val2改成"flight1": [val1, val2]),那你可以直接用Swift字典定义数组值。不过这个方案的前提是后端能正确解析这种格式,从你给出的JSON示例来看,后端大概率期望的是重复的键,所以这个方案可能不适用,但可以作为备选尝试。
关于contactPerson内的email结构问题
你提到email结构也有重复问题?看你给出的JSON示例,email对象里的"email": "a@gmail.com"是正常的键值对,并不是重复键。如果是之前代码里的写法有问题,用方案1的手动拼接方式也能一并解决。
关于passengerparameterarray的传递
直接把数组转成JSON字符串拼接是完全可行的,就像上面代码里处理的那样——用JSONSerialization把数组转成字符串,再替换到请求体模板中即可。
内容的提问来源于stack exchange,提问作者Zyfe3r
相关产品推荐
相关产品推荐

