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 Foundationstruct 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 Foundationvar 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 Foundationvar 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
.
Try:
With it you can go like this:
let obj:[String:AnyObject] = [ "array": [JSON.null, false, 0, "", [], [:]], "object":[ "null": JSON.null, "bool": true, "int": 42, "double": 3.141592653589793, "string": "a α\t弾\n𪚲", "array": [], "object": [:] ], "url":"http://blog.livedoor.com/dankogai/"]let json = JSON(obj)json.toString()json["object"]["null"].asNull // NSNull()json["object"]["bool"].asBool // truejson["object"]["int"].asInt // 42json["object"]["double"].asDouble // 3.141592653589793json["object"]["string"].asString // "a α\t弾\n𪚲"json["array"][0].asNull // NSNull()json["array"][1].asBool // falsejson["array"][2].asInt // 0json["array"][3].asString // ""
Using my library (https://github.com/isair/JSONHelper) you can do this with your json variable of type AnyObject:
var weathers = [Weather]() // If deserialization fails, JSONHelper just keeps the old value in a non-optional variable. This lets you assign default values like this.if let jsonDictionary = json as? JSONDictionary { // JSONDictionary is an alias for [String: AnyObject] weathers <-- jsonDictionary["weather"]}
Had your array not been under the key "weather", your code would have been just this:
var weathers = [Weather]()weathers <-- json
Or if you have a json string in your hands you can just pass it as well, instead of creating a JSON dictionary from the string first. The only setup you need to do is writing a Weather class or struct:
struct Weather: Deserializable { var id: String? var name: String? var description: String? var icon: String? init(data: [String: AnyObject]) { id <-- data["id"] name <-- data["name"] description <-- data["description"] icon <-- data["icon"] }}