web-dev-qa-db-ja.com

Alamofire経由でJSON配列を送信する

POSTリクエストで配列(辞書にラップされていない)を直接送信することは可能かと思います。どうやらparametersパラメーターは次のマップを取得するはずです:[String:AnyObject]?しかし、次のjsonの例を送信できるようにしたいと思います。

[
    "06786984572365",
    "06644857247565",
    "06649998782227"
]
58
fruechtemuesli

JSONをNSJSONSerializationでエンコードしてから、NSURLRequestを自分で構築することができます。たとえば、Swift 3の場合:

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

let values = ["06786984572365", "06644857247565", "06649998782227"]

request.httpBody = try! JSONSerialization.data(withJSONObject: values)

Alamofire.request(request)
    .responseJSON { response in
        // do whatever you want here
        switch response.result {
        case .failure(let error):
            print(error)

            if let data = response.data, let responseString = String(data: data, encoding: .utf8) {
                print(responseString)
            }
        case .success(let responseObject):
            print(responseObject)
        }
}

Swift 2については、この回答の 前のリビジョン を参照してください。

132
Rob

Swift 3およびAlamofire 4では、次のParametersEncodingおよびArray拡張を使用します。

import Foundation
import Alamofire

private let arrayParametersKey = "arrayParametersKey"

/// Extenstion that allows an array be sent as a request parameters
extension Array {
    /// Convert the receiver array to a `Parameters` object. 
    func asParameters() -> Parameters {
        return [arrayParametersKey: self]
    }
}


/// Convert the parameters into a json array, and it is added as the request body. 
/// The array must be sent as parameters using its `asParameters` method.
public struct ArrayEncoding: ParameterEncoding {

    /// The options for writing the parameters as JSON data.
    public let options: JSONSerialization.WritingOptions


    /// Creates a new instance of the encoding using the given options
    ///
    /// - parameter options: The options used to encode the json. Default is `[]`
    ///
    /// - returns: The new instance
    public init(options: JSONSerialization.WritingOptions = []) {
        self.options = options
    }

    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var urlRequest = try urlRequest.asURLRequest()

        guard let parameters = parameters,
            let array = parameters[arrayParametersKey] else {
                return urlRequest
        }

        do {
            let data = try JSONSerialization.data(withJSONObject: array, options: options)

            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
            }

            urlRequest.httpBody = data

        } catch {
            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
        }

        return urlRequest
    }
}

基本的に、Dictionary引数として受け入れられるように配列をParametersに変換してから、辞書から配列を取り戻し、JSON Dataに変換して、リクエスト本文。

取得したら、次の方法でリクエストを作成できます。

let values = ["06786984572365", "06644857247565", "06649998782227"]
Alamofire.request(url,
                  method: .post,
                  parameters: values.asParameters(),
                  encoding: ArrayEncoding())
51
manueGE

次に、ルーターを使用して、Thing型の配列をJSONにエンコードし、Ograを使用してOgraを実行する例を示します。

import Foundation
import Alamofire
import Orga

class Thing {
    ...
}

enum Router: URLRequestConvertible {
    static let baseURLString = "http://www.example.com"

    case UploadThings([Thing])

    private var method: Alamofire.Method {
        switch self {
        case .UploadThings:
            return .POST
        }
    }

    private var path: String {
        switch self {
        case .UploadThings:
            return "upload/things"
        }
    }

    var URLRequest: NSMutableURLRequest {
        let r = NSMutableURLRequest(URL: NSURL(string: Router.baseURLString)!.URLByAppendingPathComponent(path))
        r.HTTPMethod = method.rawValue

        switch self {
        case .UploadThings(let things):
            let custom: (URLRequestConvertible, [String:AnyObject]?) -> (NSMutableURLRequest, NSError?) = {
                (convertible, parameters) in
                var mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
                do {
                    let jsonObject = things.encode().JSONObject()
                    let data = try NSJSONSerialization.dataWithJSONObject(jsonObject, options: NSJSONWritingOptions.PrettyPrinted)
                    mutableRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
                    mutableRequest.HTTPBody = data
                    return (mutableRequest, nil)
                } catch let error as NSError {
                    return (mutableRequest, error)
                }
            }
            return ParameterEncoding.Custom(custom).encode(r, parameters: nil).0
        default:
            return r
        }
    }
}
3
Andrew Jackman

Swift 2.
以下のこのコードはオブジェクト配列をポストします。このコードはSwift 2.0でテストされています

func POST(RequestURL: String,postData:[AnyObject]?,successHandler: (String) -> (),failureHandler: (String) -> ()) -> () {

        print("POST : \(RequestURL)")

        let request = NSMutableURLRequest(URL: NSURL(string:RequestURL)!)
        request.HTTPMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        var error: NSError?
        do {
             request.HTTPBody  = try NSJSONSerialization.dataWithJSONObject(postData!, options:[])


        } catch {
            print("JSON serialization failed:  \(error)")
        }

        Alamofire.request(request)
            .responseString{ response in
                switch response.result {
                case .Success:
                    print(response.response?.statusCode)
                    print(response.description)
                    if response.response?.statusCode == 200 {
                        successHandler(response.result.value!)
                    }else{
                        failureHandler("\(response.description)")
                    }

                case .Failure(let error):
                    failureHandler("\(error)")
                }
        }

    }
3
Chamath Jeevan

JSONコンテンツをパラメーターとして送信するには、2つのアプローチがあります。

  1. Jsonを文字列として送信すると、Webサービスがサーバーでそれを解析します。

     d["completionDetail"] = "[{"YearOfCompletion":"14/03/2017","Completed":true}]"
    
  2. JSON内の各値(YearOfCompletionおよびCompleted)を順次配列の形式で渡すことができます。そして、Webサービスはそのデータを同じ順序で挿入します。この構文は次のようになります

    d["YearOfCompletion[0]"] = "1998"  
    d["YearOfCompletion[1]"] = "1997"  
    d["YearOfCompletion[2]"] = "1996"  
    
    d["Completed[0]"] = "true"  
    d["Completed[1]"] = "false"  
    d["Completed[2]"] = "true"  
    

Alamofire request Swift3.をトリガーするために、次のWebサービス呼び出し関数を辞書で使用しています。

func wsDataRequest(url:String, parameters:Dictionary<String, Any>) {
    debugPrint("Request:", url, parameters as NSDictionary, separator: "\n")

    //check for internete collection, if not availabale, don;t move forword
    if Rechability.connectedToNetwork() == false {SVProgressHUD.showError(withStatus: NSLocalizedString("No Network available! Please check your connection and try again later.", comment: "")); return}

    //
    self.request = Alamofire.request(url, method: .post, parameters: parameters)
    if let request = self.request as? DataRequest {
        request.responseString { response in
            var serializedData : Any? = nil
            var message = NSLocalizedString("Success!", comment: "")//MUST BE CHANGED TO RELEVANT RESPONSES

            //check content availability and produce serializable response
            if response.result.isSuccess == true {
                do {
                    serializedData = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.allowFragments)
                    //print(serializedData as! NSDictionary)
                    //debugPrint(message, "Response Dictionary:", serializedData ?? "Data could not be serialized", separator: "\n")
                }catch{
                    message = NSLocalizedString("Webservice Response error!", comment: "")
                    var string = String.init(data: response.data!, encoding: .utf8) as String!

                    //TO check when html coms as prefix of JSON, this is hack mush be fixed on web end. 
                    do {
                        if let index = string?.characters.index(of: "{") {
                            if let s = string?.substring(from: index) {
                                if let data = s.data(using: String.Encoding.utf8) {
                                    serializedData = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
                                    debugPrint(message, "Courtesy SUME:", serializedData ?? "Data could not be serialized", separator: "\n")
                                }
                            }
                        }
                    }catch{debugPrint(message, error.localizedDescription, "Respone String:", string ?? "No respone value.", separator: "\n")}

                    //let index: Int = text.distance(from: text.startIndex, to: range.lowerBound)
                    debugPrint(message, error.localizedDescription, "Respone String:", string ?? "No respone value.", separator: "\n")
                }

                //call finised response in all cases
                self.delegate?.finished(succes: response.result.isSuccess, and: serializedData, message: message)
            }else{
                if self.retryCounter < 1 {//this happens really frequntly so in that case this fn being called again as a retry
                    self.wsDataRequest(url: url, parameters: parameters)
                }else{
                    message = response.error?.localizedDescription ?? (NSLocalizedString("No network", comment: "")+"!")
                    SVProgressHUD.showError(withStatus: message);//this will show errror and hide Hud
                    debugPrint(message)

                    //call finised response in all cases
                    self.delay(2.0, closure: {self.delegate?.finished(succes: response.result.isSuccess, and: serializedData, message:message)})
                }
                self.retryCounter += 1
            }
        }
    }
}
0
rptwsthi

@manueGEの答えは正しい。 alamofire githubの指示によると、同様のアプローチがあります: `

struct JSONDocumentArrayEncoding: ParameterEncoding {
    private let array: [Any]
    init(array:[Any]) {
        self.array = array
    }
    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var urlRequest = urlRequest.urlRequest

        let data = try JSONSerialization.data(withJSONObject: array, options: [])

        if urlRequest!.value(forHTTPHeaderField: "Content-Type") == nil {
            urlRequest!.setValue("application/json", forHTTPHeaderField: "Content-Type")
        }

        urlRequest!.httpBody = data

        return urlRequest!
    }
}

`次に、パラメータを持つデフォルトのリクエストを使用する代わりに、リクエストをカスタマイズしてこれを呼び出します。それは辞書であるため、基本的にパラメーターを破棄します。

let headers = getHeaders()
    var urlRequest = URLRequest(url: URL(string: (ServerURL + Api))!)
    urlRequest.httpMethod = "post"
    urlRequest.allHTTPHeaderFields = headers
    let jsonArrayencoding = JSONDocumentArrayEncoding(array: documents)

    let jsonAryEncodedRequest = try? jsonArrayencoding.encode(urlRequest, with: nil)

    request = customAlamofireManager.request(jsonAryEncodedRequest!)
    request?.validate{request, response, data in
        return .success
        }
        .responseJSON { /*[unowned self] */(response) -> Void in
            ...
    }

また、データのエラーを処理する方法は非常に役立ちます。

0
Ning
let url = try Router.baseURL.asURL()

// Make Request
var urlRequest = URLRequest(url: url.appendingPathComponent(path))
urlRequest.httpMethod = "post"

// let dictArray: [[String: Any]] = []
urlRequest = try! JSONEncoding.default.encode(urlRequest, withJSONObject: dictArray)

JSON配列をアップロードするためにプロジェクトで行うこと

0
harsh_v