使用Alamofire将Json POST到API?

时间:2017-08-25 10:02:42

标签: ios json swift alamofire

我想发布一个我在服务类中创建的JSON对象并传递给networkService。

这是我的网络服务,但我收到错误

  

类型的值' [String:Any]'没有会员资料'

就行:let jsonData = json.data(using: .utf8, allowLossyConversion: false)!

    func request(json: [String:Any]) {

    let url = URL(string: urlString)!
    let jsonData = json.data(using: .utf8, allowLossyConversion: false)!

    var request = URLRequest(url: url)
    request.httpMethod = HTTPMethod.post.rawValue
    request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
    request.httpBody = jsonData

    Alamofire.request(request).responseJSON {
        (response) in
        print(response)
    }
}

我通过func参数调用func时传递了JSON的想法。

这是传入的JSON对象:

    func loginUser(data: Array<String>, deviceToken: String) {
    // create JSON
    let json = [ "login-email" : data[0],
                "login-password" : data[1],
                "login-secret" : "8A145C555C43FBA5",
                "devicetoken" : deviceToken
                ]

    networkManager.request(json: json)
}

然后我转换并将其发送到API(urlString)

是否/为什么这不起作用?

感谢

更新版本:

func request(json: [String:Any]) {

    let url = URL(string: urlString)!

    do {
        let jsonData = try JSONSerialization.data(withJSONObject: json, options:[])
        var request = URLRequest(url: url)
        request.httpMethod = HTTPMethod.post.rawValue
        request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
        request.httpBody = jsonData

        Alamofire.request(request).responseJSON {
            (response) in
            print(response)
        }
    } catch {
        print("Failed to serialise and send JSON")
    }
}

更新:添加了我的代码以拨打完成问题:

 func sendLoginRequest() {
        let userLogin = UserService.init(loginEmail: userEmail, loginPassword: userPassword, loginSecret: loginSecret, deviceToken: deviceToken)
        networkService.logUserIn(request: userLogin) { (<#JSON?#>, <#NSError?#>) in
            <#code#>
        }
    }

编辑:更新了Payload Shot:

API Payload Issue

编辑2:映射问题示例:

init?(_ json: JSON) {
    // Map API Key from top level
    guard let apiKey = json["apikey"].string else { return nil }

    // Map User at user level
    guard let userDataArray = json["user"].array else {
        fatalError("user data array NOT FOUND")
    }
    print("USER DATA IS \(userDataArray)")
    // assign user 
    for child in userDataArray {
        guard let userID = child["id"].int,
            let userEmail = child["email"].string,
            let lastName = child["lastname"].string,
            let firstName = child["firstname"].string,
            let company = child["company"].string,
            let userImage = child["image"].string,
            let jobTitle = child["jobtitle"].string
            else { return nil
        }
    }

    // Assign to model properties
    self.apiKey = apiKey
    self.userEmail = userEmail
    self.lastName = lastName
    self.firstName = firstName
    self.company = company
    self.userImage = userImage
    self.jobTitle = jobTitle
    self.userID = userID
}

1 个答案:

答案 0 :(得分:3)

我只是展示了我如何使用它。

您不必将参数转换为JSON。这是来自Alamofire的代码。

/// A dictionary of parameters to apply to a `URLRequest`.
public typealias Parameters = [String: Any]

使用此方法代替您:

Alamofire.request(url, method: method, parameters: parameters, encoding: encoding, headers: customHeaders)

试试这个: 而不是request.httpBody = jsonData,您可以在json中传递parameters

您的整个代码将是:

func request(json: [String:Any]) {

    Alamofire.request(urlString, method: .post, parameters: json, encoding: JSONEncoding.default).responseJSON {
        (response) in
        print(response)
    }

}

如果您对我的方法感兴趣:

func makePick(request: MakePickRequest, completionHandler: @escaping APICompletionHandler) {
        let parameters = request.converToParameters()
        Alamofire.request(Endpoints.makePick, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in
            self.handleResponse(response: response, completionHandler: completionHandler)
        }
    }

请求:

struct MakePickRequest: GeneralRequest {
    let eventId: Int64
    let sportId: String
    let pickType: PickType
    let betType: BetType
    let amount: Int

    func converToParameters() -> [String : String] {
        return ["event_id": String(eventId), "sport_id": sportId,
        "pick_type": pickType.rawValue, "bet_type": betType.rawValue,
        "amount": String(amount)]
    }
}

端点结构:

struct Endpoints {
    // Development baseURL
    static let baseURL = "http://myurl/"

    private static let apiVersion = "api/v1/"

    static var fullPath: String {
        return "\(baseURL)\(apiVersion)"
    }

    // MARK: - User endpoints (POST)
    static var login: String {
        return "\(fullPath)users/login"
    }

    static var signUp: String {
        return "\(fullPath)users/signup"
    }

    ...
}

在任何类之外(但必须导入SwiftyJSON):

typealias APICompletionHandler = (_ data: JSON?, _ error: NSError?) -> Void

处理回应:

private func handleResponse(response: DataResponse<Any>, completionHandler: APICompletionHandler) {
        self.printDebugInfo(response)
        switch response.result {
        case .success(let value):
            self.handleJSON(data: value, handler: completionHandler)
        case .failure(let error):
            print(error)
            completionHandler(nil, error as NSError?)
        }
    }

 private func handleJSON(data: Any, handler: APICompletionHandler) {
        let json = JSON(data)
        let serverResponse = GeneralServerResponse(json)
        if (serverResponse?.status == .ok) {
            handler(serverResponse?.data, nil)
        } else {
            handler(nil, self.parseJsonWithErrors(json))
        }
    }

GeneralServerResponse(取决于您的服务器API):

import SwiftyJSON

final class GeneralServerResponse {
    let data: JSON
    let status: Status

    init?(_ json: JSON) {
        guard let status = json["status"].int else {
            return nil
        }

        self.status = Status(status)
        self.data = json["data"]
    }

    enum Status {
        case ok
        case error
        case unauthorized

        init(_ input: Int) {
            if input >= 200 && input < 400 {
                self = .ok
            } else if input == 403 {
                self = .unauthorized
            } else {
                self = .error
            }
        }
    }
}

我的实际使用示例。

这是在外面:

func +=<K, V> ( left: inout [K : V], right: [K : V]) { for (k, v) in right { left[k] = v } }

请求示例:

func makePick(request: MakePickRequest, completionHandler: @escaping APICompletionHandler) {
        var parameters = ["auth_token": Preferences.getAuthToken()]
        parameters += request.converToParameters()
        manager.apiRequest(url: Endpoints.makePick, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in
            self.handleResponse(response: response, completionHandler: completionHandler)
        }
    }

SessionManager扩展,为所有请求添加标头:

extension SessionManager {
    func apiRequest(url: URLConvertible, method: HTTPMethod, parameters: Parameters? = nil, encoding: ParameterEncoding, headers: HTTPHeaders? = nil)  -> DataRequest {
        var customHeaders: HTTPHeaders = ["api-key" : "1wFVerFztxzhgt"]
        if let headers = headers {
            customHeaders += headers
        }
        return request(url, method: method, parameters: parameters, encoding: encoding, headers: customHeaders)
    }
}

在APIManager课程中:

private let manager: SessionManager

init() {
     manager = Alamofire.SessionManager.default
}

致电示例:

apiClient.makePick(request: request) { data, error in
        if let error = error {
            print(error.localizedDescription)
            return
        }
        if let data = data {
            // data is a JSON object, here you can parse it and create objects
        }
    }

班级示例:

import SwiftyJSON

final class MyClass {
    let id: Int
    let username: String
    let parameter: Double

    init?(_ json: JSON) {
        guard let id = json["id"].int, let username = json["username"].string,
            let parameter = json["parameter"].double else {
                return nil
        }

        self.id = id
        self.username = username
        self.parameter = parameter
    }
}