When having a nested JSON like
{
"error":{
"statusCode":422,
"name":"ValidationError",
"message":"Errors ",
"details":{
"context":"Context",
"codes":{
"password":[
"presence"
],
"email":[
"uniqueness"
]
},
"messages":{
"password":[
"can't be blank"
],
"email":[
"Email already exists"
]
}
}
}
}
And transforming to a dictionary, if we want to check the value of error->details->codes->passwod.
Probably we have to guarding nested dictionaries until we get our value like
guard let error = json["error"] as? [String: [String: Any]],
let details = error["details"] .... till we get the value ["presence"].
So, with that being said, the proposedProposed extension is
extension Dictionary where Key == String {
subscript(dotPath path: String) -> Any? {
....
}
}
json[dotPath: "error.details.codes.password"] -> ["presence"]
I've used an extension like this in a project before:
extension Dictionary where Key == String {
subscript(keyPath path: String) -> Any? {
if let index = path.firstIndex(of: ".") {
let firstPath = String(path[..<index])
let object = self[firstPath] as? [String: Any]
let remainingPath = String(path[path.index(index, offsetBy: 1)...])
return object?[keyPath: remainingPath]
} else {
return self[path]
}
}
}
// Playground testing code
let jsonObject = try JSONSerialization.jsonObject(with: json.data(using: .utf8)!) as? [String: Any]
jsonObject?[keyPath: "error.details.codes.password"]
It makes much more sense to subscript a dictionary than a string.
Interesting recursive implementation @guykogus 馃憤
I implemented for my project as well but interactive :))
Do we want this to return type Any or a generic type T?
Here's a fix: https://github.com/SwifterSwift/SwifterSwift/pull/574
Most helpful comment
I've used an extension like this in a project before:
It makes much more sense to subscript a dictionary than a string.