14

I'm using NSJSONSerialization to parse JSON in a Swift application. However, the returned dictionary consists of a complicated, deeply nested structure, making it impractical to have very long type declarations (e.g. Dictionary<String, Array<Dictionary<String, ....>>).

Is there a good way of working with such a structure in Swift, where the collection's structure is very complicated and its types aren't known until runtime?

PrairieProf
  • 174
  • 11
Bill
  • 44,502
  • 24
  • 122
  • 213

3 Answers3

12

Just grab a reference to your json data as an NSDictionary:

var dict: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

then you can reference it using subscripts:

var myValue: NSString = dict["level1"]["level2"]
Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
  • 1
    Thanks! Using NSDictionary directly helps. However, I don't think it implements subscripting: I had to call `objectForKey`. – Bill Jun 06 '14 at 03:48
  • 1
    I'm encountering the same. I need to call objectForKey on the inner items to get access to them. Not doing this seems to not only pose a problem, but crashes Xcode 6 even... – tibbon Jun 11 '14 at 20:34
  • This doesn't work for me. I have `var dict:NSDictionary = NSDictionary(contentsOfFile:"some/path"); var deepValue = conjugationTable["level1"]["level2"]["level3"]` And the compiler complains that it `Could not find an overload for 'subscript' that accepts the supplied arguments.` – NRitH Jun 17 '14 at 02:26
  • I just ran into this problem, and using Xcode 6 Beta 4 an NSDictionary is able to do only one subscript. When I try to do double subscripts to access a nested value, using json["accounts"]["active"] Xcode goes berserk and fails. Hopefully they fix this. – almel Jul 25 '14 at 15:30
  • @almel. I had the exact same problem. – dnevins Jul 27 '14 at 04:30
  • Same problem too, how to fix? – netwire Oct 25 '14 at 20:40
  • I had a similar problem, but found that the dict["level1"]["level2"] concept just wouldn't work - then I realised I had used the option: NSJSONReadingOptions.MutableLeaves instead of .MutableContainers ! (A silly error, I know, but I thought it worth mentioning in case anyone else made the same mistake...) – ChrisGNZ Mar 19 '15 at 01:24
  • 1
    @Dean In the above example (running Xcode 6.4), to get myValue as NSString, you are forced to downcast to NSString on the object. var myValue: NSString = dict["level1"]!["level2"] as! NSString would work using the example. – Jack Sep 04 '15 at 03:35
5

myDictionary["accounts"] might be an optional. Try: myDictionary["accounts"]?["active"]?

GK100
  • 3,664
  • 1
  • 26
  • 19
4

In Obj-C we could write,

cityName = myDictionary[@"photos"][@"region"][@"city"]

As several here have discovered, the above does not apply in Swift, at least it never has for me.

Here's how you do this in Swift for accessing three indices in an NSDictionary for a String,

let cityName = ((myDictionary!["photos"] as NSDictionary)["region"]! as NSDictionary)["city"]! as String`

I hope that in the next update to Swift all of that can be reduced to what we had in Obj-C.

  • It would be much easier if its cast to `NSDictionary` and use `valueForKeyPath` like `(jsonResponse as NSDictionary).valueForKeyPath("geometry.location.lat") as? Int`. But also came across another way to get nested data out of Dictionary. +1 – GoodSp33d Oct 20 '15 at 08:40
  • I have run into the same probelem. Has this been made easier? I am looking for an automated way to completely parse and typecast an entire nested dictionary/array mix json. – David Schumann Sep 22 '16 at 15:05