使用 Swift 3 解析 JSON

Posted

技术标签:

【中文标题】使用 Swift 3 解析 JSON【英文标题】:Parse JSON with Swift 3 【发布时间】:2016-09-20 13:38:43 【问题描述】:

我已经尝试让这个工作两周了。它正在使用 Swift 2 在 ios 9 上运行,但现在这似乎无缘无故地不起作用。我添加了print("[DEBUG] I was here 1/2/3/4") 来调试代码,它打印出来的只是[DEBUG] I was here 1。有任何想法吗?它让我发疯。

func downloadData() 
    //clear the arrays
    arrayPosts = [String]()
    arrayLinks = [String]()
    arrayConditions = [String]()
    arrayIDs = [String]()
    //debug
    print("[DEBUG] I was here: 1")

    //baseURL is a string with URL to JSON Endpoint
    let url = URL(string: baseURL)
    URLSession.shared.dataTask(with:url!, completionHandler: (data, response, error) in
        if error != nil 
            print("[ERROR] [DEBUG] Error with connection: \(error)")
         else 
            do 
                //debug
                print("[DEBUG] I was here: 2")
                if let json = try JSONSerialization.jsonObject(with: data!, options:[.mutableContainers, .allowFragments]) as? [[String: Any]] 
                    for item in json 
                        //debug
                        print("[DEBUG] I was here: 3")
                        if let startTime = item["current_time"] as? Int 
                            if self.defaults.integer(forKey: "startTime") == 0 
                                self.defaults.set(startTime, forKey: "startTime")
                            
                        

                        if let posts = item["posts"] as? [[String: AnyObject]] 
                            //debug
                            print("[DEBUG] I was here: 4")
                            for post in posts 
                                if let text = post["text"] as? String 
                                    if let condition = post["conditions"] as? String
                                        if let url = post["url"] as? String 
                                            if let id = post["id"] as? String 
                                                self.arrayPosts.append(text)
                                                self.arrayConditions.append(condition)
                                                self.arrayLinks.append(url)
                                                self.arrayIDs.append(id)
                                            
                                        
                                    
                                
                            

                        
                    
                
             catch 
                print("[ERROR] [DEBUG] Something went wrong during data download from the server.")
            
        

    ).resume()

这是 JSON DATA 以防万一:


    "status": "ok",
    "num_results": "4",
    "current_time": 1474386061,
    "user_time": 0,
    "posts": [
    
        "text": "If your shirt isn't tucked into your pants, then your pants are tucked into your shirt.",
        "conditions": "4",
        "url": "0",
        "time": "0",
        "id": "108"
    ,
    
        "text": "Veteran Kills Himself in Parking Lot of V.A. Hospital on Long Island",
        "conditions": "6",
        "url": "http://www.nytimes.com/2016/08/25/nyregion/veteran-kills-himself-in-parking-lot-of-va-hospital-on-long-island.html",
        "time": 1472076000,
        "id": "1472076000"
    ,
    
        "text": "Leaked Script Shows What Advisers Want Donald Trump to Say at Black Church",
        "conditions": "6",
        "url": "http://www.nytimes.com/2016/09/02/us/politics/donald-trump-black-voters-wayne-jackson.html",
        "time": 1472767200,
        "id": "1472767200"
    ,
    
        "text": "Creepy Clown Sightings in South Carolina Cause a Frenzy",
        "conditions": "6",
        "url": "http://www.nytimes.com/2016/08/31/us/creepy-clown-sightings-in-south-carolina-cause-a-frenzy.html",
        "time": 1472594400,
        "id": "1472594400"
    
    ]

【问题讨论】:

我刚刚使用虚假 URL 进行了测试,结果显示为“[DEBUG] I was here: 2”。 let url = URL(string: baseURL) 为零吗? @EricAya 理论上应该。我再次运行它以防万一它停在“[DEBUG] I was here: 1”。可能是其他问题吗?就像我使用 http 而不是 https 的事实一样? 不,@Larme 不是 @MohanSingh 抱歉回复晚了。在你回答之前我已经解决了这个问题。还是谢谢。 【参考方案1】:

试试下面的代码:

import UIKit

class ViewController: UIViewController 

   var arrayPosts = [String]()
   var arrayLinks = [String]()
   var arrayConditions = [String]()
   var arrayIDs = [String]()

    override func viewDidLoad() 
        super.viewDidLoad()
        self.downloadData()

    

    func downloadData()
    
        let url = NSURL(string: "http://getmydetails.pe.hu/test/parsejsonswift3.php") //Provided JSON data on my server. i don't know how longer it is present there!.
        let request = NSMutableURLRequest(url: url! as URL)

        let task = URLSession.shared.dataTask(with: request as URLRequest)  data,response,error in
        guard error == nil && data != nil else
        
            print("Error:",error)
            return
            

            let httpStatus = response as? HTTPURLResponse

            if httpStatus!.statusCode == 200
            
                if data?.count != 0
                
                    let responseString = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary //because JSON data started with dictionary. Not an array
                    let status = responseString["status"] as! String

                    if status == "ok"
                    
                        print("Status is :", status)

                        let timevar = responseString["current_time"] //not specified as String or Int
                        print(String(describing: timevar)) // print by converting anyobject to string

                       if let posts = responseString["posts"] as? [AnyObject] // posts started with array
                        
                        for post in posts
                            
                                let text = post["text"] as! String //specify as String
                                print(text)

                                let condition = post["conditions"] as! String
                                let url = post["url"] as! String
                                let id = post["id"] as! String
                                DispatchQueue.main.sync
                                

                                    self.arrayPosts.append(text)
                                    self.arrayConditions.append(condition)
                                    self.arrayLinks.append(url)
                                    self.arrayIDs.append(id)

                                    //optional to check
                                    self.afterJSON()
                                
                            
                        
                        else
                        
                            print("I could not find post array")
                        
                    
                    else
                    
                        print("Status is not Okay!")
                    
                
                else
                
                    print("No data got from url!")
                
            
            else
            
                print("error httpstatus code is :",httpStatus!.statusCode)
            
        
        task.resume()
    

    func afterJSON()
    
        print("Posts are:\n\t\t",arrayPosts)
        print("Conditions are:\n\t\t",arrayConditions)
        print("Links are:\n\t\t",arrayLinks)
        print("ID's are:\n\t\t",arrayIDs)

    
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    



输出如下图所示,

如果您感到困惑,请查看我的 video 适合您。

如有任何疑问,请在下方评论:D

【讨论】:

【参考方案2】:
func downloadData() 
    //clear the arrays
    arrayPosts = [String]()
    arrayLinks = [String]()
    arrayConditions = [String]()
    arrayIDs = [String]()
    //debug
    print("[DEBUG] I was here: 1")

    //baseURL is a string with URL to JSON Endpoint
    let url = URL(string: baseURL)
    let session = URLSession.shared

    let task = session.dataTask(with: url!)  (data:Data?, response:URLResponse?, error:Error?) in
        if error != nil 
            print("[ERROR] [DEBUG] Error with connection: \(error)")
         else 
            do 
                //debug
                print("[DEBUG] I was here: 2")
                if let json = try JSONSerialization.jsonObject(with: data!, options:[.mutableContainers, .allowFragments]) as? [[String: Any]] 
                    for item in json 
                        //debug
                        print("[DEBUG] I was here: 3")
                        if let startTime = item["current_time"] as? Int 
                            if self.defaults.integer(forKey: "startTime") == 0 
                                self.defaults.set(startTime, forKey: "startTime")
                            
                        

                        if let posts = item["posts"] as? [[String: AnyObject]] 
                            //debug
                            print("[DEBUG] I was here: 4")
                            for post in posts 
                                if let text = post["text"] as? String 
                                    if let condition = post["conditions"] as? String
                                        if let url = post["url"] as? String 
                                            if let id = post["id"] as? String 
                                                self.arrayPosts.append(text)
                                                self.arrayConditions.append(condition)
                                                self.arrayLinks.append(url)
                                                self.arrayIDs.append(id)
                                            
                                        
                                    
                                
                            

                        
                    
                
             catch 
                print("[ERROR] [DEBUG] Something went wrong during data download from the server.")
            
        

    
    task.resume()

【讨论】:

这似乎不起作用。它再次停在“[DEBUG] I was here 1”处。【参考方案3】:

谢谢,我按照你的代码获取数据))

    func getJSON()
    let wUrl = "http://api.fixer.io/latest"
    let Url = NSURL(string: wUrl)
    let request = NSMutableURLRequest(url: Url! as URL)

    let task = URLSession.shared.dataTask(with: request as URLRequest) data, response, error in
        guard error == nil && data != nil else
        
            print("Error:", error ?? "some error")
            return
        

        let httpStatus = response as? HTTPURLResponse
        if httpStatus!.statusCode == 200 
            if data?.count != 0 

                let resposeString = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary

                let base = resposeString["base"] as? String
                print(base ?? "")
                let date = resposeString["date"] as? String
                print(date ?? "")
                let rates = resposeString["rates"] as! Dictionary<String, AnyObject>

                for (key, value) in rates
                    print("\(key)->\(value)")

                
            
            else
            
                print("Data is emty")
            
        
        else 
            print("error httpStatus code: ", httpStatus?.statusCode ?? "")
        

    ;task.resume()



【讨论】:

以上是关于使用 Swift 3 解析 JSON的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Alamofire 在 Swift 3 中解析 JSON?

使用 Swift 3 解析 JSON

使用 Alamofire 在 swift 3 中解析 Json

如何使用 Swift 3.0 解析这个 JSON 对象

如何在 Swift 3 中使用 Alamofire 4 解析这个 json?

使用 Alamofire Swift 3 和 Xcode 8 beta 解析 JSON 没有数据