从JSON解析返回数据 - 斯威夫特

问题描述:

所以我和斯威夫特一个新手,并稍微与一般的编程。我只是一直在做这件事,因为第一年的......我试图做一个简单的应用程序,从外部JSON文件中提取数据,并将其输入到UILabels。我得到的数据拉,并追加到一个数组。从这里,它似乎退出了范围,不能在其他地方使用......我创建了一个结构来保存数据。正如你所看到的,我已经添加了打印标记来直观地看到发生了什么。从JSON解析返回数据 - 斯威夫特

struct GlobalTestimonialData { 
     var testimonialsText: [String] 
     var customerNames: [String] 
     var companyNames: [String] 
    } 

    var TestimonialData = GlobalTestimonialData(testimonialsText: [""], customerNames: [""], companyNames: [""]) 

    func getData() { 
     let requestURL: URL = URL(string: "https://szadydesigns.com/test/mobileapp/testimonials.php")! 
     let urlRequest = URLRequest(url: requestURL as URL) 
     let session = URLSession.shared 
     let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in 

      let httpResponse = response as! HTTPURLResponse 
      let statusCode = httpResponse.statusCode 

    if (statusCode == 200) { 
       print("File has been downloaded!") 
       do { 

        let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) 

        print("JSON Serialized") 

        if let JSONfile = json as? [String: AnyObject] { 
         print("JSON Reading") 
         if let testimonial = JSONfile["testimonial"] as? [String] { 
          print("Testimonials Read") 
          TestimonialData.testimonialsText.append(contentsOf: testimonial) 
          print(TestimonialData.testimonialsText) 
          print("Inside of loop Testimonial Text Number: \(TestimonialData.testimonialsText.count)") 

          if let name = JSONfile["name"] as? [String] { 
           print("Names Read") 
           TestimonialData.customerNames.append(contentsOf: name) 
           print(TestimonialData.customerNames) 
           print("Inside of loop Customers Number: \(TestimonialData.customerNames.count)") 
          } 
          if let company = JSONfile["company"] as? [String] { 
           print("Companies Read") 
           TestimonialData.companyNames.append(contentsOf: company) 
           print(TestimonialData.companyNames) 
          } 
          print("Companies: \(TestimonialData.companyNames)") 
         } 
         print("COMPANIES: \(TestimonialData.companyNames)") 
        } 
        print("Companies AGIAN: \(TestimonialData.companyNames)") 
       }catch { 
        print("Error with Json: \(error)") 
       } 
       print("Companies AGIAN AGAIN : \(TestimonialData.companyNames)") 
      } 
      print("Companies AGIAN AGAIN AGAIN: \(TestimonialData.companyNames)") 
     } 

     //Loses Scope 
     print("Companies AGIAN TIMES : \(TestimonialData.companyNames)") 
     task.resume() 

     print("Outside of loop Customers Number: \(TestimonialData.customerNames.count)") 
     print("Outside of loop Testimonial Text Number: \(TestimonialData.testimonialsText.count)") 
     print(TestimonialData.companyNames) 
    } 

我知道我错过了一些非常简单的事情......但我无所适从...任何帮助/信息都会感激!

+0

您使用的是故事板?你的代码不在任何你想链接到故事板的自定义类中,所以我很困惑你将如何显示数据。 – Bawpotter

+0

你缺少调用回调,task.resume后'打印线()'总会打印*没有数据*'因为工作dataTask'异步。在你的代码中还有另一个大的设计错误:一个自定义结构应该为每个**证明创建一个**实例,而不是保存多个数组。在Swift 3中,为JSON字典使用原生的'URL','URLRequest'和'[String:Any]'。 – vadian

+0

是的,我正在使用故事板。上面的代码是它自己的.Swift文件,以保持ViewController'干净'。 – szady

没有与此代码的几个问题:

第一:您收到的JSON是不是在你的代码期望的格式。根对象不是字典而是数组。

if let JSONfile = json as? [String: Any] { 

变化

if let JSONfile = json as? [[String: String]] { 

这也需要你遍历每个项目。

print("JSON Reading") 
for item in JSONfile { 

正如字典中的定义已经从[String:Any][String:String]as? String语句改变是不再被需要。

二:我不知道你是否意识到这一点(也许你已经这样做了),但//Loses Scope线运行第一后的码位。在Companies AGIAN AGAINCompanies AGIAN AGAIN AGAIN之前。

他们可能进一步下来的页面,但上面说是在运行该文件下载等以后执行后,其他线路已经运行后封闭线。


下面是完整的固定码(以这样的方式,你可以将它复制并粘贴到一个Xcode游乐场看到它的工作格式)。

// Xcode 8.2, Swift 3 
import Cocoa 
import PlaygroundSupport 

// Required for the download to work. 
PlaygroundPage.current.needsIndefiniteExecution = true 


struct GlobalTestimonialData { 
    var testimonialsText: [String] 
    var customerNames: [String] 
    var companyNames: [String] 
} 

var testimonialData = GlobalTestimonialData(testimonialsText: [], customerNames: [], companyNames: []) 

func getData() { 
    let requestURL: NSURL = NSURL(string: "https://szadydesigns.com/test/mobileapp/testimonials.php")! 
    let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: requestURL as URL) 
    let session = URLSession.shared 
    let task = session.dataTask(with: urlRequest as URLRequest) { (data, response, error) in 

     let httpResponse = response as! HTTPURLResponse 
     let statusCode = httpResponse.statusCode 
     if (statusCode == 200) { 
      print("File has been downloaded!") 
      do { 
       let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) 

       print("JSON Serialized") 

       if let JSONfile = json as? [[String: String]] { 
        print("JSON Reading") 
        for item in JSONfile { 
         if let testimonial = item["testimonial"] { 
          testimonialData.testimonialsText.append(testimonial) 

          if let name = item["name"] { 
           testimonialData.customerNames.append(name) 
          } 
          if let company = item["company"] { 
           testimonialData.companyNames.append(company) 
          } 
         } 
        } 
       } 
      } catch { 
       print("Error with Json: \(error)") 
      } 
     } 
     print("Companies Last: \(testimonialData.companyNames)") 
     print(" ") 
     print(testimonialData) 
    } 

    //Loses Scope 
    print("Companies 1 : \(testimonialData.companyNames)") 
    task.resume() 

    print("Before the download of the JSON Customer names count: \(testimonialData.customerNames.count)") 
    print("Before the download of the JSON Testimonial Text Number: \(testimonialData.testimonialsText.count)") 
    print(testimonialData.companyNames) 
} 

getData() 

你会得到这个输出,这有助于解释发生了什么(虽然我删除了实际的公司名称)。

Companies 1 : [] 
Before the download of the JSON Customer names count: 0 
Before the download of the JSON Testimonial Text Number: 0 
[] 
File has been downloaded! 
JSON Serialized 
JSON Reading 
Companies: ["REMOVED_1", "REMOVED_2", "REMOVED_3", "REMOVED_4"]