I have a pretty complex data structure in my app, which I need to manipulate. I am trying to keep track of how many types of bugs a player has in thier garden. There are te
Yet another approach using various overloaded Dictionary subscript implementations:
let dict = makeDictionary(fromJSONString:
"""
{
"control": {
"type": "Button",
"name": "Save",
"ui": {
"scale": 0.5,
"padding": {
"top": 24,
"bottom": 32
}
}
}
}
""")!
dict[Int.self, ["control", "ui", "padding", "top"]] // 1
dict[Int.self, "control", "ui", "padding", "top"] // 2
dict[Int.self, "control.ui.padding.top"] // 3
And the actual implementations:
extension Dictionary {
// 1
subscript(_ type: T.Type, _ pathKeys: [Key]) -> T? {
precondition(pathKeys.count > 0)
if pathKeys.count == 1 {
return self[pathKeys[0]] as? T
}
// Drill down to the innermost dictionary accessible through next-to-last key
var dict: [Key: Value]? = self
for currentKey in pathKeys.dropLast() {
dict = dict?[currentKey] as? [Key: Value]
if dict == nil {
return nil
}
}
return dict?[pathKeys.last!] as? T
}
// 2. Calls 1
subscript(_ type: T.Type, _ pathKeys: Key...) -> T? {
return self[type, pathKeys]
}
}
extension Dictionary where Key == String {
// 3. Calls 1
subscript(_ type: T.Type, _ keyPath: String) -> T? {
return self[type, keyPath.components(separatedBy: ".")]
}
}
func makeDictionary(fromJSONString jsonString: String) -> [String: Any]? {
guard let data = jsonString.data(using: .utf8)
else { return nil}
let ret = try? JSONSerialization.jsonObject(with: data, options: [])
return ret as? [String: Any]
}