Moya/Alamofire - 具有相同键的 URL 编码参数
Posted
技术标签:
【中文标题】Moya/Alamofire - 具有相同键的 URL 编码参数【英文标题】:Moya/Alamofire - URL encoded params with same keys 【发布时间】:2015-08-10 02:02:20 【问题描述】:我正在使用Moya Swift 框架构建在Alamofire 之上的网络层。
目前,我正在尝试使用具有相同键的 URL 编码参数发送请求。
即http://some-site/request?param=v1&param=v2&param=v3
我已经尝试像这样将这些参数分组到 Set 或 NSSet 或 Array 中,但没有任何帮助达到预期的结果。
["param": ["v1", "v2", "v3"]];
["param": Set(arrayLiteral: "v1", "v2", "v3")]
Moya 或 Alamofire 本身的任何帮助都将不胜感激。
编辑:这里有一些示例代码来给出基本的想法:
Api 路由器设置
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 提供者设置
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
/* ... */
)
谢谢。
【问题讨论】:
您能否指定,您的 API 是“GET”还是“POST”? @SohilR.Memon 这是 GET 请求 你能贴一些代码吗? 你能展示一下你用来测试的api吗 @SohilR.Memon 编码什么?!看,我需要做的是使用 Moya 框架发送带有具有相同键的 URL 参数的 GET 请求。将您的想法与任何网络和服务器隔离开来,以字符串的形式考虑这一点。最后我需要得到这个 URL 字符串http://some-site/request?param=v1&param=v2&param=v3
。它与 POST 和其他东西无关,只是使用 Moya 或 Alamofire 框架使用相同参数键的普通 GET 请求。你知道如何实现吗?
【参考方案1】:
所以我找到了一个实际上非常简单明了的解决方案。 阅读Alamofire的文档我发现了这个:
由于没有发布关于如何编码集合类型的规范,Alamofire 遵循将 [] 附加到数组值的键(foo[]=1&foo[]=2)的约定,并附加用方括号括起来的键用于嵌套字典值 (foo[bar]=baz)。
因此,对于这种情况,有 Custom ParameterEncoding 选项可以关闭,您可以在其中实际指定自己的实现,以实现您希望如何形成参数。
Here 的问题相同,答案相同。
【讨论】:
什么时候不使用 Moya 是个好主意?有没有使用 Moya 的替代方法? 有很多库,你的名字 :) 你可以使用 Alamofire 或 NSURLSession 并创建自己的包装器,有一些与 Moya 非常相似的东西,它是来自 Thoughtbot 的 Swish。实际上网络层通常是相同的,所以你可以在这里看看它是如何工作的并创建你自己的:) @Voronv 我看了看。 Moya 或其他网络抽象层缺少的东西是 OAuth/JWT 请求方法,用于在触发下一个请求之前刷新/更新过期的身份验证令牌。比如auth token过期了,应该在下一次moya请求之前在客户端更新token...你有什么建议吗? @user805981这根本不是问题,这是Moya在这种情况下建议的github.com/Moya/Moya/blob/master/docs/Authentication.md#oauth我个人也是这样做的,我将所有需要的修改放在传递给moya提供程序的请求回调中。在我看来,网络层库不应该为你处理所有这些东西,否则它会变成不堪重负和沉重的类似 RestKit 的东西。这是用于 OAuth 处理的小型库 github.com/trivago/Heimdallr.swift 结合它们,祝你有美好的一天:) 我正在尝试按照您在问题中提供的示例,但我不断收到Cannot convert value of type 'EndpointSampleResponse' to expected argument type 'SampleResponseClosure' (aka '() -> EndpointSampleResponse')
GIST: gist.github.com/rlam3/5392927b462e3986fff58c15eb9f704f【参考方案2】:
Moya 是个好主意,但其实我觉得只要稍微想一想,我们不用太多代码就可以用 Swift 构建一个网络抽象层。
我们的目标是:
灵活性,能够有效地编辑或添加新端点 可读性,一目了然地了解我们的 API 的工作原理 代码安全,通过类型化参数实现我们期望 Xcode 提供的所有预编译优点(完成、验证)。 易于调试,意味着能够在 Web 请求之前和之后插入日志这是我在dummy project 上得到的结果:
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
【讨论】:
所以你们没有使用 Moya? 我喜欢这个主意。在我工作的当前项目中,网络层很有用。该应用程序不应直接触摸Alamofire
。额外的网络层会获得更大的灵活性,但会增加更多的复杂性。【参考方案3】:
您可以使用格式简单地创建字符串并将其作为请求 URL 传递:
http://some-site/request?param=v1¶m=v2¶m=v3
String url: String = String(format: "http://some-site/request?param=%@¶m=%@¶m=%@", v1, v2, v3)
希望这会有所帮助!
【讨论】:
以上是关于Moya/Alamofire - 具有相同键的 URL 编码参数的主要内容,如果未能解决你的问题,请参考以下文章
SAS/PROC-SQL 从具有唯一键的表转换为具有相同键的多行表
ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象
ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象