在Swift中解析JSON数组

时间:2015-12-18 23:02:43

标签: json swift parsing

我有这个工作,但它似乎是一个非常手动的过程,我无法弄清楚如何循环循环(或如果我应该)。现在我只是测试3个变量,但最终会有大约100个。这是我的游乐场。有没有办法简化这个,所以我不必手动添加每个数组名称?

import Foundation

var json_data_url = "216.92.214.107/data_test.json"
var LRKSFOweekdayDep : [String] = [String]()
var LRKSFOweekendDep : [String] = [String]()
var SFOLRKweekdayDep : [String] = [String]()

let journeysURL:NSURL = NSURL(string: json_data_url)!
let data = NSData(contentsOfURL: journeysURL)!

do {
    let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
    print(json)

    if let dep_obj =  json as? NSDictionary {
        if let array_journey = dep_obj["journey"] as? NSArray{
            if let journies = array_journey[0] as? NSDictionary {
                if let array_dep = journies["LRKSFOweekdayDep"] as? NSDictionary{
                    if let dep = array_dep["dep"] as? NSArray {
                        for var i = 0; i < dep.count; ++i
                        {
                            let add = dep[i] as! String
                            LRKSFOweekdayDep.append(add)
                        }
                        print(LRKSFOweekdayDep)
                    }
                }
            }

            if let journies = array_journey[1] as? NSDictionary {
                if let array_dep = journies["LRKSFOweekendDep"] as? NSDictionary{
                    if let dep = array_dep["dep"] as? NSArray {
                        for var i = 0; i < dep.count; ++i
                        {
                            let add = dep[i] as! String
                            LRKSFOweekendDep.append(add)
                        }
                        print(LRKSFOweekendDep)
                    }
                }
            }

            if let journies = array_journey[2] as? NSDictionary {
                if let array_dep = journies["SFOLRKweekdayDep"] as? NSDictionary{
                    if let dep = array_dep["dep"] as? NSArray {
                        for var i = 0; i < dep.count; ++i
                        {
                            let add = dep[i] as! String
                            SFOLRKweekdayDep.append(add)
                        }
                        print(SFOLRKweekdayDep)
                    }
                }
            }
        }
    }
} catch {
    print("error serializing JSON: \(error)")
}

2 个答案:

答案 0 :(得分:1)

您可能希望使用SwiftyJSON来简化解析。

答案 1 :(得分:0)

现在,你有类似的东西:

if let dep = array_dep["dep"] as? NSArray {
    for var i = 0; i < dep.count; ++i {
        let add = dep[i] as! String
        LRKSFOweekendDep.append(add)
    }
}

可以简化为:

LRKSFOweekendDep = array_dep["dep"] as? [String]

当然,假设您将LRKSFOweekendDep定义为可选。如果它不是可选的,你可以这样做:

LRKSFOweekendDep = array_dep["dep"] as? [String] ?? []

但是,它应该是可选的。

在评论中,你说这些将会有100个。而不是为每个变量都有一个变量,我会认为你宁愿保留一个对象数组。例如,考虑:

struct Journey {
    let name: String
    let departures: [String]
}

然后,要解析您的JSON,您可以遍历结果:

let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])

var journeys = [Journey]()

if let results = json as? [String: AnyObject], let array = results["journey"] as? [[String: AnyObject]] {
    for dictionary in array {
        for (name, departures) in dictionary {
            if let departureDictionary = departures as? [String: [AnyObject]], let departureList = departureDictionary["dep"] as? [String] {
                journeys.append(Journey(name: name, departures: departureList))
            }
        }
    }
}

最后,我会反对NSData(contentsOfURL:),因为那是同步的。使用NSURLSession的{​​{1}},这是异步的。此外,如果您使用dataTaskWithURL模式,请先检查以确保它不是data!。否则,如果nil由于您无法控制的任何原因data(例如,网络服务器已关闭,互联网暂时中断等),则应用程序将崩溃而不是正常处理它。

将所有这些放在一起,你会得到类似的东西:

nil

然后你会这样使用它:

func retrieveJourneys(completionHandler: ([Journey]?, NSError?) -> ()) {
    let task = NSURLSession.sharedSession().dataTaskWithURL(journeysURL) { data, response, error in
        guard error == nil && data != nil else {
            completionHandler(nil, error)
            return
        }

        var json: [String: AnyObject]?

        do {
            json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String: AnyObject]
        } catch let parseError as NSError {
            completionHandler(nil, parseError)
        }

        var journeys = [Journey]()

        if let array = json!["journey"] as? [[String: AnyObject]] {
            for dictionary in array {
                for (name, departures) in dictionary {
                    if let departureDictionary = departures as? [String: [AnyObject]], let departureList = departureDictionary["dep"] as? [String] {
                        journeys.append(Journey(name: name, departures: departureList))
                    }
                }
            }
        }
        completionHandler(journeys, nil)
    }
    task.resume()
}

现在,上面假设您需要一个有序的旅程列表,按您收到的顺序排序。

另一方面,如果您不关心订单,但想要一种有效的方法来检索与给定密钥相关的离开,则可以使用字典,而不是:

var journeys: [Journey]?

override func viewDidLoad() {
    super.viewDidLoad()

    retrieveJourneys { journeys, error in
        guard error == nil && journeys != nil else {   // make sure it didn't have network problem
            print(error)
            return
        }

        dispatch_async(dispatch_get_main_queue()) {    // now update model on main queue
            self.journeys = journeys

            // and, for giggles and grins, this is how you might grab the first one and examine it:

            let someJourney = self.journeys![0]
            print(someJourney.name)
            print(someJourney.departures)
        }
    }
}

然后:

func retrieveDepartures(completionHandler: ([String: [String]]?, NSError?) -> ()) {
    let task = NSURLSession.sharedSession().dataTaskWithURL(journeysURL) { data, response, error in
        guard error == nil && data != nil else {
            completionHandler(nil, error)
            return
        }

        var json: [String: AnyObject]?

        do {
            json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String: AnyObject]
        } catch let parseError as NSError {
            completionHandler(nil, parseError)
        }

        var departures = [String: [String]]()

        if let array = json!["journey"] as? [[String: AnyObject]] {
            for dictionary in array {
                for (name, departureObject) in dictionary {
                    if let departureDictionary = departureObject as? [String: [AnyObject]], let departureList = departureDictionary["dep"] as? [String] {
                        departures[name] = departureList
                    }
                }
            }
        }
        completionHandler(departures, nil)
    }
    task.resume()
}