I have a URL coming in to the AppDelegate method:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
}
The URL looks like www.wesite.com/shareplace.html?placeid=123
.
How can it be converted to a dictionary for easy access?
I found some code on some website, but it's showing an error in Xcode 9:
extension URL {
var queryDictionary: [String: AnyObject]? {
return URLComponents(url: self, resolvingAgainstBaseURL: false)?
.queryItems?
.reduce([:], combine: { (var result: [String: AnyObject], queryItem) -> [String: AnyObject] in
if queryItem.value?.containsString(",") ?? false {
let array = queryItem.value?.componentsSeparatedByString(",")
result[queryItem.name] = array
}
else {
result[queryItem.name] = queryItem.value
}
return result
})
}
}
.reduce([:], combine: { (var result: [String: AnyObject], queryItem) -> [String: AnyObject] in
(var result) Parameters may not have the 'var' specifier
Simple Extension
extension URL {
var queryDictionary: [String: String]? {
guard let query = self.query else { return nil}
var queryStrings = [String: String]()
for pair in query.components(separatedBy: "&") {
let key = pair.components(separatedBy: "=")[0]
let value = pair
.components(separatedBy:"=")[1]
.replacingOccurrences(of: "+", with: " ")
.removingPercentEncoding ?? ""
queryStrings[key] = value
}
return queryStrings
}
}
USAGE
let urlString = "http://www.youtube.com/video/4bL4FI1Gz6s?hl=it_IT&iv_logging_level=3&ad_flags=0&endscreen_module=http://s.ytimg.com/yt/swfbin/endscreen-vfl6o3XZn.swf&cid=241&cust_gender=1&avg_rating=4.82280613104"
let url = URL(string: urlString)
print(url!.queryDictionary ?? "NONE")
import Foundation
// MARK: - [URLQueryItem] to [String: Any]
extension Array where Element == URLQueryItem {
func toDictionary() -> [String: Any] {
var dictionary = [String: Any]()
for queryItem in self {
guard let value = queryItem.value?.toCorrectType() else { continue }
if queryItem.name.contains("[]") {
let key = queryItem.name.replacingOccurrences(of: "[]", with: "")
let array = dictionary[key] as? [Any] ?? []
dictionary[key] = array + [value]
} else {
dictionary[queryItem.name] = value
}
}
return dictionary
}
}
extension String {
// MARK: - String to [URLQueryItem]
func toURLQueryItems() -> [URLQueryItem]? {
guard let urlString = self.removingPercentEncoding, let url = URL(string: urlString) else { return nil }
if let querItems = url.toQueryItems() { return querItems }
var urlComponents = URLComponents()
urlComponents.query = urlString
return urlComponents.queryItems
}
// MARK: - attempt to cast string to correct type (int, bool...)
func toCorrectType() -> Any {
let types: [LosslessStringConvertible.Type] = [Bool.self, Int.self, Double.self]
func cast<T>(to: T) -> Any? { return (to.self as? LosslessStringConvertible.Type)?.init(self) }
for type in types { if let value = cast(to: type) { return value } }
return self
}
}
// MARK: - URL to [URLQueryItem]
extension URL {
func toQueryItems() -> [URLQueryItem]? { return URLComponents(url: self, resolvingAgainstBaseURL: false)?.queryItems }
}
// MARK: - create [URLQueryItem] from [AnyHashable: Any] or [any]
extension URLQueryItem {
private static var _bracketsString: String { return "[]" }
static func create(from values: [Any], with key: String) -> [URLQueryItem] {
let _key = key.contains(_bracketsString) ? key : key + _bracketsString
return values.compactMap { value -> URLQueryItem? in
if value is [Any] || value is [AnyHashable: Any] { return nil }
return URLQueryItem(name: _key, value: value as? String ?? "\(value)")
}
}
static func create(from values: [AnyHashable: Any]) -> [URLQueryItem] {
return values.flatMap { element -> [URLQueryItem] in
if element.value is [AnyHashable: Any] { return [] }
let key = element.key as? String ?? "String"
if let values = element.value as? [Any] { return URLQueryItem.create(from: values, with: key) }
return [URLQueryItem(name: key, value: element.value as? String ?? "\(element.value)")]
}
}
}
// MARK: - [AnyHashable: Any] to [URLQueryItem]
extension Dictionary where Value: Any {
func toURLQueryItems() -> [URLQueryItem] { return URLQueryItem.create(from: self) }
}
url.toQueryItems()
url.toQueryItems()?.toDictionary()
urlString.toURLQueryItems()
urlString.toURLQueryItems()?.toDictionary()
urlQueryString?.toURLQueryItems()
urlQueryString?.toURLQueryItems()?.toDictionary()
let dictionary = ["aaa": [1234], "bbb": ["a", "b", "c"]]
dictionary.toURLQueryItems()
var urlString = "https://example.com/l57?condition%5B%5D=31&brand%5B%5D=289&brand%5B%5D=291&brand%5B%5D=32&year%5B%5D=23259&year%5B%5D=23757&ships_from_region%5B%5D=23684&ships_from_region%5B%5D=23683"
let url = URL(string: urlString)!
var urlQueryString = url.query
print("URL:\n\(urlString)")
print("URL query string:\n\(String(describing: urlQueryString))\n")
print("get [URLQueryItem] from URL:\n\(String(describing: url.toQueryItems()))\n")
print("get [String: Any] from URL:\n\(String(describing: url.toQueryItems()?.toDictionary()))\n")
print("get [URLQueryItem] from url string (absoluteString):\n\(String(describing: urlString.toURLQueryItems()))\n")
print("get [String:Any] from url string (absoluteString):\n\(String(describing: urlString.toURLQueryItems()?.toDictionary()))\n")
print("get [URLQueryItem] from url string (only query):\n\(String(describing: urlQueryString?.toURLQueryItems()))\n")
print("get [String:Any] from url string (only query):\n\(String(describing: urlQueryString?.toURLQueryItems()?.toDictionary()))\n")
var dict = [String: Any]()
dict = ["aaa": [1234], "bbb": [1234: 22], "ccc": ["a", "b", "c"], "ddd": [[1,2,3], [4,5,6]], "eee[]": [1,2,4], "fff": "value", "ggg": 123]
print("Dict: \(dict)")
print("Dict to [URLQueryItem]: \(dict.toURLQueryItems())")
print("Dict to query oriented dictionary: \(dict.toURLQueryItems().toDictionary())")
URL:
https://example.com/l57?condition%5B%5D=31&brand%5B%5D=289&brand%5B%5D=291&brand%5B%5D=32&year%5B%5D=23259&year%5B%5D=23757&ships_from_region%5B%5D=23684&ships_from_region%5B%5D=23683
URL query string:
Optional("condition%5B%5D=31&brand%5B%5D=289&brand%5B%5D=291&brand%5B%5D=32&year%5B%5D=23259&year%5B%5D=23757&ships_from_region%5B%5D=23684&ships_from_region%5B%5D=23683")
get [URLQueryItem] from URL:
Optional([condition[]=31, brand[]=289, brand[]=291, brand[]=32, year[]=23259, year[]=23757, ships_from_region[]=23684, ships_from_region[]=23683])
get [String: Any] from URL:
Optional(["condition": [31], "ships_from_region": [23684, 23683], "year": [23259, 23757], "brand": [289, 291, 32]])
get [URLQueryItem] from url string (absoluteString):
Optional([condition[]=31, brand[]=289, brand[]=291, brand[]=32, year[]=23259, year[]=23757, ships_from_region[]=23684, ships_from_region[]=23683])
get [String:Any] from url string (absoluteString):
Optional(["year": [23259, 23757], "ships_from_region": [23684, 23683], "condition": [31], "brand": [289, 291, 32]])
get [URLQueryItem] from url string (only query):
Optional([condition[]=31, brand[]=289, brand[]=291, brand[]=32, year[]=23259, year[]=23757, ships_from_region[]=23684, ships_from_region[]=23683])
get [String:Any] from url string (only query):
Optional(["condition": [31], "brand": [289, 291, 32], "ships_from_region": [23684, 23683], "year": [23259, 23757]])
Dict: ["ccc": ["a", "b", "c"], "eee[]": [1, 2, 4], "bbb": [1234: 22], "fff": "value", "ddd": [[1, 2, 3], [4, 5, 6]], "aaa": [1234], "ggg": 123]
Dict to [URLQueryItem]: [ccc[]=a, ccc[]=b, ccc[]=c, ggg=123, fff=value, aaa[]=1234, eee[]=1, eee[]=2, eee[]=4]
Dict to query oriented dictionary: ["ccc": ["a", "b", "c"], "aaa": [1234], "fff": "value", "eee": [1, 2, 4], "ggg": 123]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With