Parse json in Swift, AnyObject type

This works fine for me in the playground and in the terminal using env xcrun swift

UPDATED FOR SWIFT 4 AND CODABLE

Here is a Swift 4 example using the Codable protocol.

var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"

struct Weather: Codable {
    let id: Int
    let main: String
    let description: String
    let icon: String
}

struct Result: Codable {
    let weather: [Weather]
}

do {
    let weather = try JSONDecoder().decode(Result.self, from: jsonStr.data(using: .utf8)!)
    print(weather)
}
catch {
    print(error)
}

UPDATED FOR SWIFT 3.0

I have updated the code for Swift 3 and also showed how to wrap the parsed JSON into objects. Thanks for all the up votes!

import Foundation

struct Weather {
    let id: Int
    let main: String
    let description: String
    let icon: String
}

extension Weather {
    init?(json: [String: Any]) {
        guard
            let id = json["id"] as? Int,
            let main = json["main"] as? String,
            let description = json["description"] as? String,
            let icon = json["icon"] as? String
        else { return nil }
        self.id = id
        self.main = main
        self.description = description
        self.icon = icon
    }
}

var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"

enum JSONParseError: Error {
    case notADictionary
    case missingWeatherObjects
}

var data = jsonStr.data(using: String.Encoding.ascii, allowLossyConversion: false)
do {
    var json = try JSONSerialization.jsonObject(with: data!, options: [])
    guard let dict = json as? [String: Any] else { throw JSONParseError.notADictionary }
    guard let weatherJSON = dict["weather"] as? [[String: Any]] else { throw JSONParseError.missingWeatherObjects }
    let weather = weatherJSON.flatMap(Weather.init)
    print(weather)
}
catch {
    print(error)
}

— Previous Answer —

import Foundation

var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"
var data = jsonStr.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
var localError: NSError?
var json: AnyObject! = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &localError)

if let dict = json as? [String: AnyObject] {
    if let weather = dict["weather"] as? [AnyObject] {
        for dict2 in weather {
            let id = dict2["id"]
            let main = dict2["main"]
            let description = dict2["description"]
            println(id)
            println(main)
            println(description)
        }
    }
}

Since I’m still getting up-votes for this answer, I figured I would revisit it for Swift 2.0:

import Foundation

var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"
var data = jsonStr.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
do {
    var json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)

    if let dict = json as? [String: AnyObject] {
        if let weather = dict["weather"] as? [AnyObject] {
            for dict2 in weather {
                let id = dict2["id"] as? Int
                let main = dict2["main"] as? String
                let description = dict2["description"] as? String
                print(id)
                print(main)
                print(description)
            }
        }
    }

}
catch {
    print(error)
}

The biggest difference is that the variable json is no longer an optional type and the do/try/catch syntax. I also went ahead and typed id, main, and description.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)