Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
545 views
in Technique[技术] by (71.8m points)

ios - URL Encode Alamofire GET params with SwiftyJSON

I am trying to have Alamofire send the following parameter in a GET request but it's sending gibberish:

filters={"$and":[{"name":{"$bw":"duke"},"country":"gb"}]}
//www.example.com/example?filters={"$and":[{"name":{"$bw":"duke"},"country":"gb"}]}
//Obviously URL encoded

This is my code:

let jsonObject = ["$and":[["name":["$bw":string], "country":"gb"]]]
let json = JSON(jsonObject)
print(json)

outputs

{ "$and" : [ { "name" : { "$bw" : "duke" }, "country" : "gb" } ] }

This is my params request:

let params = ["filters" : json.rawValue, "limit":"1", "KEY":"my_key"]

This is what AlamoFire is sending:

KEY=my_key&
filters[$and][][country]=gb&
filters[$and][][name][$bw]=duke&
limit=1 

As you can see the filter parameter is a complete mess. What am I doing wrong?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By default Alamofire encodes the parameters using Parameter List in the POST body. Try changing the encoding to JSON. This way Alamofire will serialize the dictionary as a JSON string as you expect:

let parameters = [
    "foo": [1,2,3],
    "bar": [
        "baz": "qux"
    ]
]

Alamofire.request(.POST, "http://httpbin.org/post", parameters: parameters, encoding: .JSON)
// HTTP body: {"foo": [1, 2, 3], "bar": {"baz": "qux"}}

Or using your code:

let string = "duke"
let jsonObject = ["$and":[["name":["$bw":string], "country":"gb"]]]
let json = JSON(jsonObject)
let params = ["filters" : json.rawValue, "limit":"1", "KEY":"my_key"]

Alamofire.request(.POST, "http://httpbin.org/post", parameters: params, encoding: .JSON)
    .responseString(encoding: NSUTF8StringEncoding) { request, response, content, error in
        NSLog("Request: %@ - %@
%@", request.HTTPMethod!, request.URL!, request.HTTPBody.map { body in NSString(data: body, encoding: NSUTF8StringEncoding) ?? "" } ?? "")
        if let response = response {
            NSLog("Response: %@
%@", response, content ?? "")
        }
}

Gets the output:

Request: POST - http://httpbin.org/post
{"filters":{"$and":[{"name":{"$bw":"duke"},"country":"gb"}]},"limit":"1","KEY":"my_key"}

EDIT: URL-Encoded JSON in the GET parameters

If you want to send a URL-Encoded JSON in the GET parameters you have to generate first the JSON string and then pass it as a string in your parameters dictionary:

SWIFT 1

let string = "duke"
let jsonObject = ["$and":[["name":["$bw":string], "country":"gb"]]]
let json = JSON(jsonObject)

// Generate the string representation of the JSON value
let jsonString = json.rawString(encoding: NSUTF8StringEncoding, options: nil)!
let params = ["filters" : jsonString, "limit": "1", "KEY": "my_key"]


Alamofire.request(.GET, "http://httpbin.org/post", parameters: params)
    .responseString(encoding: NSUTF8StringEncoding) { request, response, content, error in
        NSLog("Request: %@ - %@
%@", request.HTTPMethod!, request.URL!, request.HTTPBody.map { body in NSString(data: body, encoding: NSUTF8StringEncoding) ?? "" } ?? "")
        if let response = response {
            NSLog("Response: %@
%@", response, content ?? "")
        }
}

SWIFT 2

let string = "duke"
let jsonObject = ["$and":[["name":["$bw":string], "country":"gb"]]]
let json = JSON(jsonObject)

// Generate the string representation of the JSON value
let jsonString = json.rawString(NSUTF8StringEncoding)!
let params = ["filters" : jsonString, "limit": "1", "KEY": "my_key"]

Alamofire.request(.GET, "http://httpbin.org/post", parameters: params)
    .responseString(encoding: NSUTF8StringEncoding) { request, response, result in
        NSLog("Request: %@ - %@
%@", request!.HTTPMethod!, request!.URL!, request!.HTTPBody.map { body in NSString(data: body, encoding: NSUTF8StringEncoding) ?? "" } ?? "")
        switch result {
        case .Success(let value):
            NSLog("Response with content: %@", value)
        case .Failure(let data, _):
            NSLog("Response with error: %@", data ?? NSData())
        }
}

SWIFT 3 and Alamofire 4.0

let string = "duke"
let jsonObject = ["$and":[["name":["$bw":string], "country":"gb"]]]
let json = JSON(jsonObject)

// Generate the string representation of the JSON value
let jsonString = json.rawString(.utf8)!
let params = ["filters" : jsonString, "limit": "1", "KEY": "my_key"]

Alamofire.request("http://httpbin.org/post", method: .get, parameters: params)
    .responseString { response in
        #if DEBUG
            let request = response.request
            NSLog("Request: (request!.httpMethod!) - (request!.url!.absoluteString)
(request!.httpBody.map { body in String(data: body, encoding: .utf8) ?? "" } ?? "")")
            switch response.result {
            case .success(let value):
                print("Response with content (value)")
            case .failure(let error):
                print("Response with error: (error as NSError): (response.data ?? Data())")
            }
        #endif
}

This generates a GET request with the following URL:

http://httpbin.org/post?KEY=my_key&filters=%7B%22%24and%22%3A%5B%7B%22name%22%3A%7B%22%24bw%22%3A%22duke%22%7D%2C%22country%22%3A%22gb%22%7D%5D%7D&limit=1

That URL-Decoded is:

http://httpbin.org/post?KEY=my_key&filters={"$and":[{"name":{"$bw":"duke"},"country":"gb"}]}&limit=1

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...