Search code examples
iosswiftalamofire

Moya/Alamofire - URL encoded params with same keys


I'm using Moya Swift framework for networking layer which is constructed on top of Alamofire.

Currently, I'm trying to send request with URL encoded parameters that have same keys.

i.e. http://some-site/request?param=v1&param=v2&param=v3

I've already tried to group these params into Set or NSSet or Array like this but nothing helps to achieve desired result.

["param": ["v1", "v2", "v3"]];

["param": Set(arrayLiteral: "v1", "v2", "v3")]

Any help would be appreciated either with Moya or with Alamofire itself.

Edit: Here is some sample code to give basic idea:

Api Router setup

import Moya

// MARK:- Enum Declaration

enum ApiRouter {
    case XAuth(login: String, password: String)
    case SomeRequest(params: [String])
}

// MARK:- Moya Path

extension ApiRouter: MoyaPath {
    var path: String {
        switch self {
        case .XAuth:
            return "/authorization"
        case .SomeRequest:
            return "/some-request"
        }
    }
}

// MARK:- Moya Target

extension ApiRouter: MoyaTarget {
    private var base: String {
        return "http://some-site"
    }
    var baseURL: NSURL {
        return NSURL(string: base)!
    }

    var parameters: [String: AnyObject] {
        switch self {
        case .XAuth(let login, let password):
            return [
                "email": login,
                "password": password
            ]
        case .SomeRequest(let params):
            return [
                "params": params
            ]
    }

    var method: Moya.Method {
        switch self {
        case .XAuth:
            return .POST
        case .SomeRequest,
            return .GET
        }
    }

    var sampleData: NSData {
        switch self {
        case .XAuth:
            return "{}".dataUsingEncoding(NSUTF8StringEncoding)
        case .ServiceRequests:
            return "{}".dataUsingEncoding(NSUTF8StringEncoding)
        }
    }
}

Api Provider setup

    let endpointsClosure = { (target: ApiRouter) -> Endpoint<ApiRouter> in
    let endpoint = Endpoint<ApiRouter>(
        URL: target.baseURL.URLByAppendingPathComponent(target.path).absoluteString!,
        sampleResponse: EndpointSampleResponse.Success(200, { target.sampleData }),
        method: target.method,
        parameters: target.parameters,
        parameterEncoding: parameterEncoding(target)
    )
    switch target {
    case .XAuth:
        return endpoint
    default:
        let token = "some-token"
        return endpoint.endpointByAddingHTTPHeaderFields(["Authorization": "Bearer: \(token)"])
    }
}

func parameterEncoding(target: ApiRouter) -> Moya.ParameterEncoding {
    switch target {
    case .XAuth:
        return .JSON
    case .SomeRequest:
        return .URL
    }
}

let apiProvider = MoyaProvider(endpointsClosure: endpointsClosure)

apiProvider.request(ApiRouter.SomeRequest(params: ["v1", "v2", "v3"], completion: { (data, statusCode, response, error) in
    /* ... */
})

Thanks.


Solution

  • So I found a solution which is actually pretty simple and obvious. Reading Alamofire's documentation I found this:

    Since there is no published specification for how to encode collection types, Alamofire follows the convention of appending [] to the key for array values (foo[]=1&foo[]=2), and appending the key surrounded by square brackets for nested dictionary values (foo[bar]=baz).

    So, for this cases there's Custom ParameterEncoding option which takes closure where you can actually specify your own implementation of how you want parameters to be formed.

    Here's the same question with the same answer.