alp*_*nec 39 parsing json swift
我正在尝试解析json,但我对数据类型有一些困难,特别是AnyObject类型+向下转换.
让我们考虑下面的json(它是一个完整的json的摘录).
{ "weather":
[
{
"id":804,
"main":"Clouds",
"description":"overcast clouds",
"icon":"04d"
}
],
}
Run Code Online (Sandbox Code Playgroud)
对我来说,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)
Run Code Online (Sandbox Code Playgroud)
我的json是AnyObject类型!(我用来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
}
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误
Playground execution failed: error: <EXPR>:28:56: error: '[AnyObject]' is not a subtype of '(String, AnyObject)'
if let weatherDictionary = dict["weather"] as? [AnyObject] {
Run Code Online (Sandbox Code Playgroud)
我不明白为什么将dict ["weather"]与(String,AnyObject)的子类型进行比较而不是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]."
Run Code Online (Sandbox Code Playgroud)
编辑
我忘了强行解开字典["天气"]!
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)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我们应该仔细检查是否存在第一个Optional.
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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
Dan*_* T. 35
这对我在操场和终端使用都很好 env xcrun swift
更新SWIFT 4和CODABLE
这是使用Codable协议的Swift 4示例.
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)
}
Run Code Online (Sandbox Code Playgroud)
更新SWIFT 3.0
我已经更新了Swift 3的代码,还展示了如何将解析后的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)
}
Run Code Online (Sandbox Code Playgroud)
- 以前的答案 -
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于我仍然在为这个答案获得投票,我想我会为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)
}
Run Code Online (Sandbox Code Playgroud)
最大的区别是变量json不再是可选类型和do/try/catch语法.我还继续和类型id,main以及description.
尝试:
有了它,你可以这样:
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 // ""
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49221 次 |
| 最近记录: |