Alamofire queryString编码会扭曲JSON参数

时间:2018-12-29 10:14:31

标签: json swift alamofire multipart

好的想法是:

  • 将视频文件作为多部分请求上传

  • 将令牌设置为标头

  • 正文应编码为queryString

对于这种json类型,一切正常:

{
  "description": "opi",
  "playerJersey": [
    {
      "playerId": "5c209d446ea7260b82fb0933",
      "playerJerseyColor": "Black"
    }
  ],
  "title": "nas",
  "playerList": [
    {
      "_id": "5c209d446ea7260b82fb0933"
    }
  ]
}

但是,如果数据中有多个播放器,并且json看起来像这样:

{
  "description": "opi",
  "playerJersey": [
    {
      "playerId": "5c209d446ea7260b82fb0933",
      "playerJerseyColor": "Black"
    },
    {
      "playerId": "5c209d4c6ea7260b82fb0934",
      "playerJerseyColor": "Yellow"
    }
  ],
  "title": "nas",
  "playerList": [
    {
      "_id": "5c209d446ea7260b82fb0933"
    },
    {
      "_id": "5c209d4c6ea7260b82fb0934"
    }
  ]
}

我已经拦截了请求并打印出url并在线对其进行了解码,这是这样形成的:

http://194.106.182.88:3000/video/upload/5c209d1a6ea7260b82fb0932?description=opi&playerJersey%5B%5D%5BplayerId%5D=5c209d446ea7260b82fb0933&playerJersey%5B%5D%5BplayerJerseyColor%5D=Black&playerJersey%5B%5D%5BplayerId%5D=5c209d4c6ea7260b82fb0934&playerJersey%5B%5D%5BplayerJerseyColor%5D=Yellow&playerList%5B%5D%5B_id%5D=5c209d446ea7260b82fb0933&playerList%5B%5D%5B_id%5D=5c209d4c6ea7260b82fb0934&title=nas

或有些美化和%解码:

http://194.106.182.88:3000/video/upload/5c209d1a6ea7260b82fb0932?description=opi
&playerJersey[]
          [playerId]=5c209d446ea7260b82fb0933
&playerJersey[]
          [playerJerseyColor]=Black
&playerJersey[]
          [playerId]=5c209d4c6ea7260b82fb0934
&playerJersey[]
          [playerJerseyColor]=Yellow
&playerList[]
          [_id]=5c209d446ea7260b82fb0933
&playerList[]
           [_id]=5c209d4c6ea7260b82fb0934
&title=nas

这似乎不太正确(最后两个_id应该是它们自己的独立字典/ json,并且此编码似乎将它们合并到一个playerList中,并且我从服务器获得的响应与此再次相关,并且看起来像这个:

  

[数据]:701个字节[结果]:成功:{“状态”:500,“消息”:“内部   服务器错误!“,”错误“:{”错误“:{”玩家列表“:{”消息“:”发布到   数组值\“ [{_id:['5c209d446ea7260b82fb0933',   '5c209d4c6ea7260b82fb0934']} \“在路径上   \“ playerList \”“,” name“:” CastError“,” stringValue“:” \“ [{_id:[   '5c209d446ea7260b82fb0933','5c209d4c6ea7260b82fb0934']}   ] \“”,“种类”:“数组”,“值”:[{“ _ id”:[“ 5c209d446ea7260b82fb0933”,“ 5c209d4c6ea7260b82fb0934”]}]],“路径”:“玩家列表”,“原因”:{}} },“ _ message”:“视频   验证失败”,“消息”:“视频验证失败:playerList:   值\“ [{_id:[   '5c209d446ea7260b82fb0933','5c209d4c6ea7260b82fb0934']}] \“在路径上   \“ playerList \”“,”名称“:” ValidationError“}}

我在此行加粗了:

[ { _id: [ '5c209d446ea7260b82fb0933', '5c209d4c6ea7260b82fb0934' ] } ]

是的,这不是我想要发送的(开始时再次查看示例json)

这是我的代码。

func postRequestForVideoStreamUpload(_ videoUrl: String, _ videoTitle: String, _ videoDescription: String, _ players: [PlayerIDInput],_ jerseys: [PlayerJersey], _ accessToken: String? = nil, callback: @escaping (() -> Void)) {
        guard let userId = UserDefaults.standard.currentUserID() else { return }
        guard let streamUrl = URL(string: [API.baseUrl, API.videoUpload, userId].joined(separator: "/")) else { return }
        let fileUrl = URL(fileURLWithPath: videoUrl)

        let accessToken = UserDefaults.standard.accessToken()

        var request = URLRequest(url: streamUrl)
        var finalRequest: URLRequest?
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type");
        if let token = accessToken {
            request.setValue(token, forHTTPHeaderField: "x-access-token")
        }

        var playersArr: [[String : String]] = []
        for player in players {
            var tempDict = Dictionary<String, String>()
            tempDict["_id"] = player.playerId
            playersArr.append(tempDict)
        }

        var jerseyArr: [[String : String]] = []
        for jersey in jerseys {
            var tempDict = Dictionary<String, String>()
            tempDict["playerId"] = jersey.playerId
            tempDict["playerJerseyColor"] = jersey.playerJerseyColor
            jerseyArr.append(tempDict)
        }

        let parameters: [String : Any] = [
            "title": videoTitle,
            "description": videoDescription,
            "playerList": playersArr,
            "playerJersey": jerseyArr
            ]

        do {
            try finalRequest =  Alamofire.URLEncoding(destination: .queryString).encode(request, with: parameters)
        } catch let err {
            print(err)
            return
        }

        do {
            let fileData = try Data(contentsOf: fileUrl)

            Alamofire.upload(multipartFormData: { (multiPartFormData) in
                multiPartFormData.append(fileData, withName: "withNamePolje", fileName: "fileNamePolje", mimeType: "video/mp4")
            }, with: finalRequest!) { (result) in
                switch result {
                case .success(request: let upload, _,  _):
                    upload.responseString { response in
                        debugPrint(response)
                    }.uploadProgress { progress in // main queue by default
                        DispatchQueue.main.async {
                            print("Upload Progress: \(progress.fractionCompleted)")
                        }
                    }
                    upload.response { (response) in
                        callback()
                    }
                    return
                case .failure(let err):
                    print(err)
                }
            }
        } catch let err {
            print(err)
        }
    }

我尝试过的一些事情:

1)在将原始字典/ json用作finalRequest的参数之前,有无数种制作原始字典/ json的方法。

2)替换:

try finalRequest =  Alamofire.URLEncoding(destination: .queryString).encode(request, with: parameters)

具有:

try finalRequest =  Alamofire.URLEncoding(destination: .queryString, arrayEncoding: .brackets).encode(request, with: parameters)

(尝试了.brackets和.noBrackets)

0 个答案:

没有答案