Swifterswift: Nested Dictionary String Key value

Created on 25 Sep 2018  路  4Comments  路  Source: SwifterSwift/SwifterSwift

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"]

enhancement feature request good first issue help wanted

Most helpful comment

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.

All 4 comments

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?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marcocapano picture marcocapano  路  5Comments

bjimenezned picture bjimenezned  路  3Comments

omaralbeik picture omaralbeik  路  3Comments

pawurb picture pawurb  路  3Comments

pawurb picture pawurb  路  3Comments