在Swift,AnyObjecttypes中parsingjson

我试图parsing一个JSON,但我有一些数据types的困难,尤其是AnyObjecttypes+向下转换。

让我们考虑下面的json(这是一个完整的json的提取)。

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

对我来说,json可以描述如下:

 - json: Dictionary of type [String: AnyObject] (or NSDictionary, so = [NSObject, AnyObject] in Xcode 6 b3) - "weather": Array of type [AnyObject] (or NSArray) - Dictionary of type [String: AnyObject] (or NSDictionary, so = [NSObject, AnyObject] in Xcode 6 b3) 

我的JSON是AnyObjecttypes的! (我使用JSONObjectWithData从URL获取JSON)。

然后我想访问天气词典。 这是我写的代码。

 var localError: NSError? var json: AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &localError) if let dict = json as? [String: AnyObject] { if let weatherDictionary = dict["weather"] as? [AnyObject] { // Do stuff with the weatherDictionary } } 

这是我得到的错误

 Playground execution failed: error: <EXPR>:28:56: error: '[AnyObject]' is not a subtype of '(String, AnyObject)' if let weatherDictionary = dict["weather"] as? [AnyObject] { 

我不明白为什么字典[“天气”]与(String,AnyObject)的子types而不是AnyObject进行比较。

我把我的字典声明为[String:AnyObject],所以我使用String键访问一个值,我应该有一个AnyObject,不是吗?

如果我使用NSDictionary而不是[String:AnyObject],它的工作原理。

如果我使用NSArray而不是[AnyObject],它可以工作。

 - The Xcode 6 beta 3 release notes tell that "NSDictionary* is now imported from Objective-C APIs as [NSObject : AnyObject].". - And the Swift book: "When you bridge from an NSArray object to a Swift array, the resulting array is of type [AnyObject]." 

编辑

我忘了强制解开字典(“天气”)!

 if let dict = json as? [String: AnyObject] { println(dict) if let weatherDictionary = dict["weather"]! as? [AnyObject] { println("\nWeather dictionary:\n\n\(weatherDictionary)") if let descriptionString = weatherDictionary[0]["description"]! as? String { println("\nDescription of the weather is: \(descriptionString)") } } } 

请注意,我们应该再次检查是否存在第一个可选项。

 if let dict = json as? [String: AnyObject] { for key in ["weather", "traffic"] { if let dictValue = dict[key] { if let subArray = dictValue as? [AnyObject] { println(subArray[0]) } } else { println("Key '\(key)' not found") } } } 

这对我在操场上和terminal使用env xcrun swift

更新SWIFT 3.0

我已经更新了Swift 3的代码,并展示了如何将parsing的JSON封装到对象中。 感谢所有的赞成票!

 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) } 

– 以前的答案 –

 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) } } } 

由于我仍然为这个答案起来票,我想我会重温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) } 

最大的区别是variablesjson不再是一个可选types和do / try / catch语法。 我也继续inputidmaindescription

尝试:

有了它,你可以这样走:

 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 // true json["object"]["int"].asInt // 42 json["object"]["double"].asDouble // 3.141592653589793 json["object"]["string"].asString // "a α\t弾\n𪚲" json["array"][0].asNull // NSNull() json["array"][1].asBool // false json["array"][2].asInt // 0 json["array"][3].asString // "" 

使用我的库( https://github.com/isair/JSONHelper ),你可以用你的types为AnyObject的jsonvariables来做到这一点:

 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"] } 

如果你的数组没有在关键的“天气”之下,你的代码就是这样的:

 var weathers = [Weather]() weathers <-- json 

或者,如果您手中有jsonstring,则也可以传递它,而不是先从string中创buildJSON字典。 你需要做的唯一的设置是写一个Weather类或结构:

 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"] } }