I have a URL coming in to the AppDelegate method:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) ->
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(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"], "ffffd": [[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", "ffffd": [[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]