accessing nested dictionary from api in swift

Holy cow…there MUST be a better way to access formatted in

floorplan_summary: {
    bedrooms: {
        low: 1,
        high: 2,
        formatted: "1 - 2 Beds"
    }
}

than doing this:

  • Set UITableView's height to the height of its content with Auto Layout
  • Prevent NSURLSession from caching responses
  • Xcode reference a framework instead of link binary with libraries
  • Swift Image retrieving from Parse sdk - getting crashed
  • Swift, use string name to reference a variable
  • How to randomize the case of letters in a string in Swift?
  •     if data["floorplan_summary"]?["bedrooms"] != nil {
            let bedrooms = data["floorplan_summary"]?["bedrooms"] as NSDictionary
            if bedrooms["formatted"] != nil{
                self.beds = bedrooms["formatted"] as String
            }
        }
    

    I want to just do this:

    self.beds = data["floorplan_summary"]?["bedrooms"]?["formatted"] as String
    

    ..but at each level the object seems to be cast as AnyObject. Why can the compiler assume this data["floorplan_summary"]?["bedrooms"] but not the above?

    How can I simplify this?

    3 Solutions Collect From Internet About “accessing nested dictionary from api in swift”

    Assuming data is NSDictionary, or [String:AnyObject]. You can:

    let beds = data["floorplan_summary"]?["bedrooms"]??["formatted"] as? String // -> as String?
                                                      ^
    

    You need extra ? because data["floorplan_summary"]?["bedrooms"] returns AnyObject??. You have to unwrap it twice.

    Why it returns AnyObject??? Because data["floorplan_summary"]? is AnyObject, and AnyObject may or may not have subscript. So, the first ? means, “If it has subscript“, and the second means “If subscript returns non nil“.

    If you are wanting the syntax you described, I’d suggest using SwiftyJSON. It seems pretty popular, and it’s all implemented in a single swift file so not hard to add it to your project. It would look something like this.

    let floorPlanSummary = JSON(data: yourRawData)
    self.beds = floorPlanSummery["bedrooms"]["formatted"].string
    

    You may be able to just invoke data.valueForKeyPath("floorplan_summary.bedrooms.formatted")