How to access deeply nested dictionaries in Swift

Another option: You could try calling dict.value( forKeyPath: "ladybug.spotted.red" )!


So I just tried this with Swift 5:

import Foundation

var d = [ "ladybug" : [ "spotted" : [ "red" : 123 ] ] ] as [String:Any]

(d as NSDictionary).value(forKeyPath: "ladybug.spotted.red")

and it works, but this is probably the best way:

d["ladybug"]?["spotted"]?["red"]

I had the same issue, where I wanted to get boolValue nested in dictionary.

{
  "Level1": {
    "leve2": {
      "code": 0,
      "boolValue": 1
    }
  }
}

I tried a lot of solution but those didn't worked for me as i was missing type casting. So I used following code to get the boolValue from json, where json is a nested dictionary of type [String:Any].

let boolValue = ((json["level1"]
    as? [String: Any])?["level2"]
    as? [String: Any])?["boolValue"] as? Bool

When working with dictionaries you have to remember that a key might not exist in the dictionary. For this reason, dictionaries always return optionals. So each time you access the dictionary by key you have to unwrap at each level as follows:

bugsDict["ladybug"]!["spotted"]!["red"]!++

I presume you know about optionals, but just to be clear, use the exclamation mark if you are 100% sure the key exists in the dictionary, otherwise it's better to use the question mark:

bugsDict["ladybug"]?["spotted"]?["red"]?++

Addendum: This is the code I used for testing in playground:

var colorsDict = [String : Int]()
var patternsDict =  [String : [String : Int]] ()
var bugsDict = [String : [String : [String : Int]]] ()

colorsDict["red"] = 1
patternsDict["spotted"] = colorsDict
bugsDict["ladybug"] = patternsDict


bugsDict["ladybug"]!["spotted"]!["red"]!++ // Prints 1
bugsDict["ladybug"]!["spotted"]!["red"]!++ // Prints 2
bugsDict["ladybug"]!["spotted"]!["red"]!++ // Prints 3
bugsDict["ladybug"]!["spotted"]!["red"]! // Prints 4

My primary use case was reading ad-hoc values from a deep dictionary. None of the answers given worked for me in my Swift 3.1 project, so I went looking and found Ole Begemann's excellent extension for Swift dictionaries, with a detailed explanation on how it works.

I've made a Github gist with the Swift file I made for using it, and I welcome feedback.

To use it, you can add the Keypath.swift into your project, and then you can simply use a keyPath subscript syntax on any [String:Any] dictionary as follows.

Considering you have a JSON object like so:

{
    "name":"John",
    "age":30,
    "cars": {
        "car1":"Ford",
        "car2":"BMW",
        "car3":"Fiat"
    }
}

stored in a dictionary var dict:[String:Any]. You could use the following syntax to get to the various depths of the object.

if let name = data[keyPath:"name"] as? String{
    // name has "John"
}
if let age = data[keyPath:"age"] as? Int{
    // age has 30
}
if let car1 = data[keyPath:"cars.car1"] as? String{
    // car1 has "Ford"
}

Note that the extension supports writing into nested dictionaries as well, but I haven't yet used this.

I still haven't found a way to access arrays within dictionary objects using this, but it's a start! I'm looking for a JSON Pointer implementation for Swift but haven't found one, yet.