解析 JSON Swift 下标错误
Parse JSON Swift Subscript Error
我正在尝试解析 swift 中的某些 JSON,但出现 'subscript' 错误。我试图转换为 AnyObject 而不是 NSDictinary 但无济于事。相当卡住。任何帮助,将不胜感激。这是我的代码:
override func viewDidLoad() {
super.viewDidLoad()
splitViewController!.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
UINavigationBar.appearance().barTintColor = UIColor(red: 52.0/255.0, green: 170.0/255.0, blue: 220.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.whiteColor()]
let url = NSURL(string:"https://www.kimonolabs.com/api/7flcy3qm?apikey=gNq3hB1j0NtBdAvXJLEFx8JaqtDG8y6Y")!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in
if error != nil {
print(error)
} else {
if let data = data {
//print(NSString(data: data, encoding: NSUTF8StringEncoding))
do { let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
if jsonResult!.count > 0 {
if let items = jsonResult["Date"] as? NSArray {
print(items)
}
}
} catch {
}
}
}
}
task.resume()
}
好吧,别咬我的脑袋,但有没有可能jsonResult中没有"Date"键?这就是我解释 "subscript" 错误的方式。
此外,当我从您正在使用的 URL 中获取数据时,没有 "Date" 对象。
...稍后...
唐,这是我为完成您在最近评论中所要求的内容而提出的:
// JSONTest
import UIKit
class ViewController: UIViewController {
// MARK: Properties
var events: [EventRecord] = []
// MARK: Types
struct EventRecord {
struct Event {
let href: NSURL?
let text: String?
}
let event: Event
let hasta: String?
let location: String?
}
// MARK: View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
splitViewController!.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
UINavigationBar.appearance().barTintColor = UIColor(red: 52.0/255.0, green: 170.0/255.0, blue: 220.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.whiteColor()]
let url = NSURL(string:"https://www.kimonolabs.com/api/7flcy3qm?apikey=gNq3hB1j0NtBdAvXJLEFx8JaqtDG8y6Y")!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in
if error != nil {
print(error)
} else {
if let data = data {
//print(NSString(data: data, encoding: NSUTF8StringEncoding))
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
if jsonResult!.count > 0 {
if let results = jsonResult!["results"] as? NSDictionary, collection2 = results["collection2"] as? NSArray {
for entry in collection2 {
if let dict = entry as? NSDictionary {
self.events.append(self.processEntryDict(dict))
}
else {
// BARF!
}
}
print("events:\(self.events)")
}
}
} catch {
print("In catch block")
}
}
}
}
task.resume()
}
// MARK: Helper methods
/// processEntryDict creates an `EventRecord` from the individual entry passed to the method and returns it to the caller.
func processEntryDict(entry: NSDictionary) -> EventRecord {
// Each object in the "collection2" array is a dictionary of the form:
// {
// "Event": {
// "href": "http://www.vigolowcost.com/event/ceos-e-mares-de-felipe-aranda/?instance_id=31511",
// "text": "“Ceos e Mares” de Felipe Aranda"
// },
// "Hasta": "oct 23 todo el día",
// "Location": "Detrás do Marco, Vigo",
// "index": 2,
// "url": "http://www.vigolowcost.com/agenda/"
// },
//
let hasta = entry["Hasta"] as? String
let location = entry["Location"] as? String
var eventHref: NSURL?
var eventText: String?
if let eventDict = entry["Event"] as? NSDictionary {
if let hrefText = eventDict["href"] as? String {
eventHref = NSURL(string: hrefText)
}
eventText = eventDict["text"] as? String
}
let eventRecordEvent = EventRecord.Event(href: eventHref, text: eventText)
return EventRecord(event: eventRecordEvent, hasta: hasta, location: location)
}
}
请注意,我添加了内容以确保 "results" 和 "collection2" 存在,然后提供一种遍历 "collection2."
中的条目的方法
我现在写的 class 更接近于我在做我认为你正在尝试做的事情时的方式。不过,我也会将 session.dataTaskWithURL
调用的 completionHandler 拉到它自己的方法中。
这里有几点需要注意:
- 我使用
// MARK: xxx
来隔离功能。这些注释会在 Xcode 的 class 标识符下拉列表中生成命名分隔符。 (见下文)
- 我创建了一个
EventRecord
结构来保存每个事件的信息。这将使与事件数组的交互变得更加容易,因为它现在是 Swift Array
个 EventRecord
对象。 (属性 命名为 events
。)这还允许您自动利用 Swift 提供的所有严格类型检查。
- 我使用新的
processEntryDict(:)
函数处理 collection2
中的每个条目。这是我尝试使用更短的方法保持代码模块化的另一种方式。这简化了测试、维护、文档编制和故障排除。
processEntryDict
声明之前的行是一个特殊标记(注意三个斜杠)。如果您选择单击 processEntryDict
,您会注意到我放在那里的描述。 Objective-C 这个东西超级强大。我不确定它是否与 Swift. 一样有用
- 现在,当您 运行 程序时,它会将事件数组发送到调试控制台。显然,除了事件列表之外,您还想做其他事情,但这应该为您推进项目提供了良好的开端。
如果您需要更多帮助或希望我向您解释其中的任何内容,请告诉我。
我将"collection2"的第一位内容的图片留在这里,因为它可以作为一个很好的参考。
我正在尝试解析 swift 中的某些 JSON,但出现 'subscript' 错误。我试图转换为 AnyObject 而不是 NSDictinary 但无济于事。相当卡住。任何帮助,将不胜感激。这是我的代码:
override func viewDidLoad() {
super.viewDidLoad()
splitViewController!.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
UINavigationBar.appearance().barTintColor = UIColor(red: 52.0/255.0, green: 170.0/255.0, blue: 220.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.whiteColor()]
let url = NSURL(string:"https://www.kimonolabs.com/api/7flcy3qm?apikey=gNq3hB1j0NtBdAvXJLEFx8JaqtDG8y6Y")!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in
if error != nil {
print(error)
} else {
if let data = data {
//print(NSString(data: data, encoding: NSUTF8StringEncoding))
do { let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
if jsonResult!.count > 0 {
if let items = jsonResult["Date"] as? NSArray {
print(items)
}
}
} catch {
}
}
}
}
task.resume()
}
好吧,别咬我的脑袋,但有没有可能jsonResult中没有"Date"键?这就是我解释 "subscript" 错误的方式。
此外,当我从您正在使用的 URL 中获取数据时,没有 "Date" 对象。
...稍后...
唐,这是我为完成您在最近评论中所要求的内容而提出的:
// JSONTest
import UIKit
class ViewController: UIViewController {
// MARK: Properties
var events: [EventRecord] = []
// MARK: Types
struct EventRecord {
struct Event {
let href: NSURL?
let text: String?
}
let event: Event
let hasta: String?
let location: String?
}
// MARK: View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
splitViewController!.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
UINavigationBar.appearance().barTintColor = UIColor(red: 52.0/255.0, green: 170.0/255.0, blue: 220.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.whiteColor()]
let url = NSURL(string:"https://www.kimonolabs.com/api/7flcy3qm?apikey=gNq3hB1j0NtBdAvXJLEFx8JaqtDG8y6Y")!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in
if error != nil {
print(error)
} else {
if let data = data {
//print(NSString(data: data, encoding: NSUTF8StringEncoding))
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
if jsonResult!.count > 0 {
if let results = jsonResult!["results"] as? NSDictionary, collection2 = results["collection2"] as? NSArray {
for entry in collection2 {
if let dict = entry as? NSDictionary {
self.events.append(self.processEntryDict(dict))
}
else {
// BARF!
}
}
print("events:\(self.events)")
}
}
} catch {
print("In catch block")
}
}
}
}
task.resume()
}
// MARK: Helper methods
/// processEntryDict creates an `EventRecord` from the individual entry passed to the method and returns it to the caller.
func processEntryDict(entry: NSDictionary) -> EventRecord {
// Each object in the "collection2" array is a dictionary of the form:
// {
// "Event": {
// "href": "http://www.vigolowcost.com/event/ceos-e-mares-de-felipe-aranda/?instance_id=31511",
// "text": "“Ceos e Mares” de Felipe Aranda"
// },
// "Hasta": "oct 23 todo el día",
// "Location": "Detrás do Marco, Vigo",
// "index": 2,
// "url": "http://www.vigolowcost.com/agenda/"
// },
//
let hasta = entry["Hasta"] as? String
let location = entry["Location"] as? String
var eventHref: NSURL?
var eventText: String?
if let eventDict = entry["Event"] as? NSDictionary {
if let hrefText = eventDict["href"] as? String {
eventHref = NSURL(string: hrefText)
}
eventText = eventDict["text"] as? String
}
let eventRecordEvent = EventRecord.Event(href: eventHref, text: eventText)
return EventRecord(event: eventRecordEvent, hasta: hasta, location: location)
}
}
请注意,我添加了内容以确保 "results" 和 "collection2" 存在,然后提供一种遍历 "collection2."
中的条目的方法我现在写的 class 更接近于我在做我认为你正在尝试做的事情时的方式。不过,我也会将 session.dataTaskWithURL
调用的 completionHandler 拉到它自己的方法中。
这里有几点需要注意:
- 我使用
// MARK: xxx
来隔离功能。这些注释会在 Xcode 的 class 标识符下拉列表中生成命名分隔符。 (见下文) - 我创建了一个
EventRecord
结构来保存每个事件的信息。这将使与事件数组的交互变得更加容易,因为它现在是 SwiftArray
个EventRecord
对象。 (属性 命名为events
。)这还允许您自动利用 Swift 提供的所有严格类型检查。 - 我使用新的
processEntryDict(:)
函数处理collection2
中的每个条目。这是我尝试使用更短的方法保持代码模块化的另一种方式。这简化了测试、维护、文档编制和故障排除。 processEntryDict
声明之前的行是一个特殊标记(注意三个斜杠)。如果您选择单击processEntryDict
,您会注意到我放在那里的描述。 Objective-C 这个东西超级强大。我不确定它是否与 Swift. 一样有用
- 现在,当您 运行 程序时,它会将事件数组发送到调试控制台。显然,除了事件列表之外,您还想做其他事情,但这应该为您推进项目提供了良好的开端。
如果您需要更多帮助或希望我向您解释其中的任何内容,请告诉我。
我将"collection2"的第一位内容的图片留在这里,因为它可以作为一个很好的参考。