Moya / Alamofire - URL-encoded parameters with the same keys

I use Moya Swift for the network layer, which is built on top of Alamofire .

I'm currently trying to send a request with URL-encoded parameters that have the same keys.

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

I already tried to group these parameters into Set or NSSet or Array, but nothing helps to achieve the desired result.

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

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

Any help would be appreciated either with Moya or with Alamofir himself.

Edit: Here is a sample code that gives a basic idea:

Configure Api Router

 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) } } } 

Configure Api Provider

  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.

+5
source share
3 answers

So, I found a solution that is actually quite simple and obvious. Reading Alamofire documentation I found this:

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

So, for this case, there is the option Custom Parameter Encoding , which closes where you can actually specify your own implementation of how you want the parameters to be generated.

Here is the same question with the same answer.

+7
source

Moya is a good idea, but I really feel that with some thinking we can build a layer of network abstraction using Swift without much code.

Our goal:

  • Flexibility to efficiently edit or add new endpoints.
  • Readability to have an idea of ​​how our API works at a glance.
  • Code security, with typed parameters allowing all the compilation requirements (completion, verification) to be expected from Xcode.
  • Easy debugging, which means the ability to insert logs before and after web requests.

Here is what I ended up with :

 public class API { public static let baseURL: String = "http://colourlovers.com/api" public enum Endpoints { case Colors(String) case Palettes(String) case Patterns(String) public var method: Alamofire.Method { switch self { case .Colors, .Palettes, .Patterns: return Alamofire.Method.GET } } public var path: String { switch self { case .Colors: return baseURL+"/colors" case .Palettes: return baseURL+"/palettes" case .Patterns: return baseURL+"/patterns" } } public var parameters: [String : AnyObject] { var parameters = ["format":"json"] switch self { case .Colors(let keywords): parameters["keywords"] = keywords break case .Palettes(let keywords): parameters["keywords"] = keywords break case .Patterns(let keywords): parameters["keywords"] = keywords break } return parameters } } public static func request( endpoint: API.Endpoints, completionHandler: Response<AnyObject, NSError> -> Void) -> Request { let request = Manager.sharedInstance.request( endpoint.method, endpoint.path, parameters: endpoint.parameters, encoding: .URL, headers: nil ).responseJSON { response in if (response.result.error) != nil { DDLogError("\n<----\n" + response.result.error!.description) completionHandler(response) } else { DDLogInfo("\n<----\n" + response.response!.description) completionHandler(response) } } DDLogInfo("\n---->\n" + request.description) return request } } 
+4
source

You can simply create the String format and pass it as the request URL:

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

 String url: String = String(format: "http://some-site/request?param=%@&param=%@&param=%@", v1, v2, v3) 

Hope this helps!

0
source

All Articles