Reputation: 8942
I have a dictionary as [String:Any]
.Now i want to convert this dictionary keys & value as key=value&key=value
.I have created below extension to work but it didn't work for me.
extension Dictionary {
var queryString: String? {
var output: String = ""
for (key,value) in self {
output += "\(key)=\(value)\(&)"
}
return output
}
}
Upvotes: 19
Views: 20883
Reputation: 2195
I wrote this helper fn, which I thought was clean:
private static func queryStringParamsToString(_ dictionary: [String: Any]) -> String {
return dictionary
.map({(key, value) in "\(key)=\(value)"})
.joined(separator: "&")
.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
}
Upvotes: 0
Reputation: 816
For anyone that wants the "short, short" version.
Condensed using map, you don't need the forEach or for loops. Also protocol constrained for type enforcement on the dictionary.
extension Dictionary where Key : StringProtocol, Value : StringProtocol {
var queryString: String {
self.map { "\($0)=\($1)" }.joined(separator: "&")
}
}
Upvotes: 0
Reputation: 2751
var populatedDictionary = ["key1": "value1", "key2": "value2"]
extension Dictionary {
var queryString: String {
var output: String = ""
for (key,value) in self {
output += "\(key)=\(value)&"
}
output = String(output.characters.dropLast())
return output
}
}
print(populatedDictionary.queryString)
// Output : key1=value1&key2=value2
Hope it helps. Happy Coding!!
Upvotes: 12
Reputation: 37
Add this function to your controller
func getQueryString(params : [String : Any])-> String{
let urlParams = params.compactMap({ (key, value) -> String in
return "\(key)=\(value)"
}).joined(separator: "&")
var urlString = "?" + urlParams
if let url = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed){
urlString = url
}
return urlString
}
Example
self.getQueryString(params: ["name" : "deep ios developer" , "age" :22])
Upvotes: 0
Reputation: 629
Compact version of @luckyShubhra's answer
Swift 5.0
extension Dictionary {
var queryString: String {
var output: String = ""
forEach({ output += "\($0.key)=\($0.value)&" })
output = String(output.dropLast())
return output
}
}
Usage
let populatedDictionary = ["key1": "value1", "key2": "value2"]
let urlQuery = populatedDictionary.queryString
print(urlQuery)
Upvotes: 3
Reputation: 1127
protocol ParametersConvertible {
func asParameters() -> [String:Any]
}
protocol QueryStringConvertible {
func asQuery() -> String
}
extension QueryStringConvertible where Self: ParametersConvertible {
func asQuery() -> String {
var queries: [URLQueryItem] = []
for (key, value) in self.asParameters() {
queries.append(.init(name: key, value: "\(value)"))
}
guard var components = URLComponents(string: "") else {
return ""
}
components.queryItems = queries
return components.percentEncodedQuery ?? ""
}
}
Upvotes: 1
Reputation: 31
Same as @KKRocks with update for swift 4.1.2
func queryItems(dictionary: [String:Any]) -> String {
var components = URLComponents()
print(components.url!)
components.queryItems = dictionary.map {
URLQueryItem(name: $0, value: String(describing: $1))
}
return (components.url?.absoluteString)!
}
Upvotes: 3
Reputation: 756
import Foundation
extension URL {
var queryItemsDictionary: [String: String] {
var queryItemsDictionary = [String: String]()
// we replace the "+" to space and then encode space to "%20" otherwise after creating URLComponents object
// it's not possible to distinguish the real percent from the space in the original URL
let plusEncodedString = self.absoluteString.replacingOccurrences(of: "+", with: "%20")
if let queryItems = URLComponents(string: plusEncodedString)?.queryItems {
queryItems.forEach { queryItemsDictionary[$0.name] = $0.value }
}
return queryItemsDictionary
}
}
That extension will allow you to parse URL where you have both encoded + sign and space with plus, for example:
https://stackoverflow.com/?q=First+question&email=mail%[email protected]
That extension will parse "q" as "First question" and "email" as "[email protected]"
Upvotes: 1
Reputation: 462
Another Swift-esque approach:
let params = [
"id": 2,
"name": "Test"
]
let urlParams = params.flatMap({ (key, value) -> String in
return "\(key)=\(value)"
}).joined(separator: "&")
Upvotes: 27
Reputation: 16180
Use NSURLQueryItem.
An NSURLQueryItem object represents a single name/value pair for an item in the query portion of a URL. You use query items with the queryItems property of an NSURLComponents object.
To create one use the designated initializer queryItemWithName:value:
and then add them to NSURLComponents
to generate an NSURL
. For example:
OBJECTIVE-C:
NSDictionary *queryDictionary = @{ @"q": @"ios", @"count": @"10" };
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in queryDictionary) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryDictionary[key]]];
}
components.queryItems = queryItems;
NSURL *url = components.URL; // http://stackoverflow.com?q=ios&count=10
Swift:
let queryDictionary = [ "q": "ios", "count": "10" ]
var components = URLComponents()
components.queryItems = queryDictionary.map {
URLQueryItem(name: $0, value: $1)
}
let URL = components.url
Upvotes: 29
Reputation: 13903
extension Dictionary {
var queryString: String? {
return self.reduce("") { "\($0!)\($1.0)=\($1.1)&" }
}
}
Upvotes: 5
Reputation: 8322
Try this :
func queryItems(dictionary: [String:Any]) -> String {
var components = URLComponents()
print(components.url!)
components.queryItems = dictionary.map {
URLQueryItem(name: $0, value: $1)
}
return (components.url?.absoluteString)!
}
Upvotes: 2