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

如何在multipart/form-data请求中传递JSON数组类型参数

multipart/form-data请求传递多元素package_json参数实现方案

问题描述

需要在Content-Type为multipart/form-data的请求中传递参数,单值场景下package_json参数可以正常传递,但传递包含多个对象的JSON数组格式package_json时失败。
现有封装的网络请求方法仅支持[String: String]类型的普通文本参数,以及Data类型的图片参数,单值场景的参数写法如下:

let param = [
       "outletId : "1",
       "vehicleId" : "1",
       "instructions" : tvInstructions.text,
       "package_json" : "[{\"packageId\":\"1\"}]",
       "addressId" : "1"
]

当前使用的上传请求封装代码:

func postrequest(_ request: String, onPath imagesData:[Data]?,_ imageName : String, andParameter parameters: [String:String]?, withCompletion response: @escaping serviceCompletion) {
    let headers: HTTPHeaders
    headers = ["Content-type": "multipart/form-data"]
    AF.upload(multipartFormData: { multiPart in
        if let allParams = parameters {
            for (key, value) in allParams {
                multiPart.append(value.data(using: .utf8)!, withName: key)
            }
        }
        for imageData in imagesData ?? [] {
            multiPart.append(imageData, withName: "\(imageName)", fileName: "file.jpg", mimeType: "image/jpg")
        }
    }, to: request, usingThreshold: UInt64.init(),
       method: .post,
       headers:  headers).response { (res) in
        if((res.error == nil)){
            do {
                response(res.data,res.error)
            }
        }
        else{
            response(res.data,res.error)
        }
    }
}

需要传递的多元素package_json格式为:[{"packageId": 1}, {"packageId": 2}, {"packageId": 3}],尝试修改方法支持[String: Any]类型参数未成功。
调用封装方法的示例代码:

func sendData() {
    let param = [
        "outletId" : "1",
        "vehicleId" : "1",
        "instructions" : tvInstructions.text,
        "package_json" : "[{\"packageId\":\"1\"}]",
        "addressId" : "1"
    ]

    ApiNetworkManager.shared.postrequest(Api.completeUrl, onPath: [], "", andParameter: param) { (response, err) in
        ApiNetworkManager.shared.hideHud()
        debugPrint(param)
        let json = JSON.init(response!)
        debugPrint(json)
        if err == nil {
            if err == nil && response != nil {
                if json.dictionaryValue["success"]?.stringValue == "1" {
                    // 业务逻辑
                }
                else{
                    let message = json.dictionaryValue["message"]?.stringValue
                    self.showAlert(Message: message ?? "Error")
                }

            } else {
                print(err?.localizedDescription as Any)
                let message = json.dictionaryValue["message"]?.stringValue
                self.showAlert(Message: message ?? "Error")
            }
        }
        else{
            ApiNetworkManager.shared.hideHud()
            let message = err?.localizedDescription
            self.showAlert(Message: message ?? "Error")
        }
    }
}

参数说明截图

解决方案

不需要修改现有网络封装的参数类型,直接把多元素的JSON数组序列化成合法的JSON字符串,作为package_json的value传入即可,和单值场景的传参逻辑完全一致。

具体实现步骤

  • 先构造需要传递的package_json原生数组对象
// 多包裹数据数组
let packageList = [
    ["packageId": "1"],
    ["packageId": "2"],
    ["packageId": "3"]
]
  • 用系统JSONSerialization把数组序列化为JSON字符串,注意处理转义问题
var packageJsonStr = ""
if let jsonData = try? JSONSerialization.data(withJSONObject: packageList, options: []),
   let jsonStr = String(data: jsonData, encoding: .utf8) {
    packageJsonStr = jsonStr
}
  • 把生成的JSON字符串直接放入参数字典即可,不需要改动现有网络封装
let param = [
    "outletId" : "1",
    "vehicleId" : "1",
    "instructions" : tvInstructions.text ?? "",
    "package_json" : packageJsonStr,
    "addressId" : "1"
]

注意事项

  • 不要手动拼接JSON字符串,容易出现转义错误、格式非法的问题,必须通过序列化方法生成合法JSON字符串
  • 确认后端要求的packageId字段类型是字符串还是数字,如果要求数字类型,构造数组时直接传整型值即可,序列化后会自动生成不带引号的数字格式
  • 现有封装逻辑里是把参数值转成utf8编码的Data追加到multipart表单,JSON字符串本身就是纯文本,完全兼容现有逻辑,不需要修改封装层代码

内容的提问来源于stack exchange,提问作者Mel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:24:17