TechChain
TechChain

Reputation: 8942

Convert dictionary to query string in swift?

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

Answers (12)

aashah7
aashah7

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

Peter Suwara
Peter Suwara

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

luckyShubhra
luckyShubhra

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

Kuldeep Singh
Kuldeep Singh

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

Rashesh Bosamiya
Rashesh Bosamiya

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

Mike Demidov
Mike Demidov

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

Jonny Mac
Jonny Mac

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

George
George

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

kyleturner
kyleturner

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

Lal Krishna
Lal Krishna

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

NRitH
NRitH

Reputation: 13903

extension Dictionary {
    var queryString: String? {
        return self.reduce("") { "\($0!)\($1.0)=\($1.1)&" }
    }
}

Upvotes: 5

KKRocks
KKRocks

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

Related Questions