You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Alamofire传参时的‘字典字面量包含重复键’错误?

解决Alamofire请求中重复键参数的传递问题

Hey,我之前对接SOAP API的时候也碰到过一模一样的问题——Swift的Dictionary本身就不允许存在重复键,所以你直接用[String: Any]定义参数肯定会触发Dictionary literal contains duplicate keys错误。针对你的场景,这里有几个实用的解决方案:

方案1:手动构建HTTP请求体(最适配SOAP场景)

SOAP请求本质是基于HTTP的结构化请求(不管是XML还是JSON格式),我们可以绕过Swift字典的限制,直接拼接符合后端要求的JSON字符串作为请求体,这样就能完美保留重复键了。

具体步骤如下:

  1. 先写出符合要求的JSON模板,把动态变量用占位符替换
  2. 将动态变量(比如邮箱、航班数据等)转成字符串后替换到模板中
  3. 把最终的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:56:55