Last active
February 24, 2018 18:03
-
-
Save ts95/7d3928d266522511882c41bd2b941d6b to your computer and use it in GitHub Desktop.
Extracting keys and values from a path in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
enum PathParamsError: Error { | |
case unbalanced | |
case nonExistentParam(key: String) | |
case invalidConversion(value: String, type: String) | |
var localizedDescription: String { | |
switch self { | |
case .unbalanced: | |
return "The number of keys didn't correspond with the number of values" | |
case .nonExistentParam(let key): | |
return "There is no value for the key \(key)" | |
case .invalidConversion(let value, let type): | |
return "Couldn't convert the value \(value) to the specified type \(type)" | |
} | |
} | |
} | |
/** | |
Used to extract path parameters from a path. | |
*/ | |
struct PathParams { | |
private let params: [String : String] | |
init(path: String) throws { | |
let parts = path.split(separator: "/") | |
guard parts.count % 2 == 0 else { throw PathParamsError.unbalanced } | |
let values = stride(from: 0, to: parts.count, by: 2).map { (index) -> (String, String) in | |
(parts[index].lowercased(), "\(parts[index+1])") | |
} | |
params = Dictionary(uniqueKeysWithValues: values) | |
} | |
func optionalValue<T: LosslessStringConvertible>(forKey key: String, _ type: T.Type) throws -> T? { | |
guard let stringValue = params[key.lowercased()] else { return nil } | |
guard let value = T(stringValue) else { | |
throw PathParamsError.invalidConversion(value: stringValue, type: String(describing: T.self)) } | |
return value | |
} | |
func value<T: LosslessStringConvertible>(forKey key: String, _ type: T.Type) throws -> T { | |
guard let value = try optionalValue(forKey: key, type) else { | |
throw PathParamsError.nonExistentParam(key: key.lowercased()) } | |
return value | |
} | |
} | |
// Usage | |
do { | |
let params = try PathParams(path: "/customerid/8945834/receiptid/36235432/category/seafood") | |
let category = try params.value(forKey: "category", String.self) | |
let customerId = try params.value(forKey: "customerid", Int.self) | |
let receiptId = try params.value(forKey: "receiptid", Int.self) | |
let sauceType = try params.optionalValue(forKey: "sauce", String.self) | |
print("Category:", category) | |
print("Customer ID:", customerId) | |
print("Receipt ID:", receiptId) | |
if let sauceType = sauceType { | |
print("Sauce: \(sauceType)") | |
} | |
} catch { | |
if let error = error as? PathParamsError { | |
print(error.localizedDescription) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment