Swift 3.0 中的 JSON 解析失败

Posted

技术标签:

【中文标题】Swift 3.0 中的 JSON 解析失败【英文标题】:JSON parsing fails in Swift 3.0 【发布时间】:2017-08-08 07:24:38 【问题描述】:

我正在尝试将 JSON 数据转换为 Swift 3.0 格式,但出现错误。

这是我的 JSON 数据:

"items": [
  
   "kind": "youtube#searchResult",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/fJgYDRLJbQIA4cQD71Hu-VtHYuM\"",
   "id": 
    "kind": "youtube#video",
    "videoId": "diVd_vpuons"
   ,
   "snippet": 
    "publishedAt": "2015-07-16T13:47:55.000Z",
    "channelId": "UC1iwdTRSV1Z2DMopttg8ocA",
    "title": "Bengali Pala Kirtan | New Bhajan Kirtan | 2015 |  Sabitri Satyaban | Shanta Das | Gold Disc",
    "description": "Watch The New Bengali Pala Kirtan By Shanta Das \"Sabitri Satyaban \". Song : Sabitri Satyaban Album : Sabitri Satyaban Singer : Shanta Das Music By ...",
    "thumbnails": 
     "default": 
      "url": "",
      "width": 120,
      "height": 90
     ,
     "medium": 
      "url": "",
      "width": 320,
      "height": 180
     ,
     "high": 
      "url": "",
      "width": 480,
      "height": 360
     
    ,
    "channelTitle": "RDC Banglar Geeti",
    "liveBroadcastContent": "none"
   
,

这是我的 Swift 代码:

func getChannelDetails(_ useChannelIDParam: Bool) 
    var urlString: String!
    if !useChannelIDParam 
        urlString = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLbhFoUkf_GY6us_3RYg7U_NeNbqlc2AXY&key=AIzaSyAop5T2uSqj4Mw9nAE740za7mAHHiRwO2M"
    

    let targetURL = URL(string: urlString)

    performGetRequest(targetURL, completion:  (data, HTTPStatusCode, error) -> Void in
        if HTTPStatusCode == 200 && error == nil 

            do 
                // Convert the JSON data to a dictionary.
                let resultsDict = try JSONSerialization.jsonObject(with: data!, options: []) as! Dictionary<String, Any>

                // Get all playlist items ("items" array).
                let items: Array<Dictionary<String, Any>> = resultsDict["items"] as! Array<Dictionary<String, Any>>

                // Use a loop to go through all video items.
                for i in 0 ..< items.count 

                    var desiredValuesDict: Dictionary<String, Any> = Dictionary<String, Any>()

                    let objDicit = (items[i] as Dictionary<String, Any>)["id"] as! Dictionary<String, Any>

                    desiredValuesDict["videoID"] =  (objDicit["videoID"] as! Dictionary<String, Any>) ["videoId"]


                    let snippetDict = (items[i] as Dictionary<String, Any>)["snippet"] as! Dictionary<String, Any>

                    // Get the snippet dictionary that contains the desired data.

                    // Create a new dictionary to store only the values we care about.

                    desiredValuesDict["title"] = snippetDict["title"]

                    desiredValuesDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<String, Any>)["high"] as! Dictionary<String, Any>)["url"]


                    //desiredValuesDict["videoID"] =  (snippetDict["resourceId"] as! Dictionary<String, Any>) ["videoId"]


                    // Save the channel's uploaded videos playlist ID.

                    // Append the desiredValuesDict dictionary to the following array.
                    self.channelsDataArray.append(desiredValuesDict)

                    // Reload the tableview.
                    self.tblVideos.reloadData()

                    // Load the next channel data (if exist).
                
             catch 
                print(error)
            

         else 
            print("HTTP Status Code = \(HTTPStatusCode)")
            print("Error while loading channel details: \(String(describing: error))")
        
        self.viewWait.isHidden = true
    )

标题和图片已显示,但出现以下错误:

线程信号 sigabrt xcode

【问题讨论】:

我建议你使用第三方解析器或使用if let 语法进行深入研究,第一个非常好,让生活和代码变得简单***.com/a/41037513/3535583 【参考方案1】:

这将有助于清除源代码

let urlString = "The URL"
    let targetURL = URL(string: urlString)
    performGetRequest(targetURL, completion:  (data, HTTPStatusCode, error) ->  in
        if let error = error 
            //do something with the error
        
        else 
            do 
                if let resultsDict = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any] 
                    if let items = resultDict["items"] as? [[String:Any]] 

                        //var parsedItems = [[String:Any]]()

                        for item in items 

                            var desiredValues = [String:Any]()

                            //get the videoId
                            if let id = item["id"] as? [String:Any], let videoId = id["videoId"] as? String 
                                desiredValues["videoId"] = videoId
                            

                            //get title and thumbnail from snippet
                            if let snippet = item["snippet"] as? [String:Any] 
                                if let title = snippet["title"] 
                                    desiredValues["title"] = title
                                

                                if let thumbanail = snippet["thumbnails"] as? [String:Any], let highValues = thumbanail["high"] as? [String:Any], let url = highValues["url"] as? String 
                                    desiredValues["url"] = url
                                
                            

                            self.channelsDataArray.append(desiredValues)

                        

                        DispatchQueue.main.async 
                            self.tblVideos.reloadData()
                        
                    
                
            
            catch (let error)
                print("Error while parsing data: \(error.localizedDescription)")
            
        
    

如果你将所有的值都放在 channelsDataArray 中,然后像访问它一样

override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let playerViewController = segue.destination as? PlayerViewController 
        playerViewController.videoID = channelsDataArray[selectedVideoIndex]["videoID"] as! String
    

尝试用不同的功能下载图片,如下所示

func getImage(from urlString:String) -> UIImage? 
    if let url = URL(string: urlString) 
        do 
             let imageContent = try Data(contentsOf: url)

            //we have image dat
            let image = UIImage(data: imageContent)

            return image
        
        catch 
            print("Unable to get image data")
        
    
    return nil

您可能想尝试使用 SDWebImage 或其他图像库来使 tableView 上的平滑滚动成为可能。或执行以下操作

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    var cell = tableView.dequeueReusableCell(withIdentifier: "idCellChannel", for: indexPath)

    let channelTitleLabel = cell.viewWithTag(10) as! UILabel
    let thumbnailImageView = cell.viewWithTag(12) as! UIImageView
    let channelDetails = channelsDataArray[indexPath.row]

    channelTitleLabel.text = channelDetails["title"] as? String

    DispatchQueue.global(qos: .background).async 
        if let imageURL = channelDetails["url"] as? String 
            if let image = getImage(from: imageURL) 
                thumbnailImageView.image = image
            
        
    
    return cell

【讨论】:

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

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

JSON图像解析IOS Swift 3.0

在 Swift 3.0 中访问从 iTunes API 解析的 JSON 对象

如何在 Swift 3.0 中的控制器之间传递 JSON 数据?

如何让 JSON 中的日期格式在 ruby 与 Swift 间保持一致

如何让 JSON 中的日期格式在 ruby 与 Swift 间保持一致