簡體   English   中英

JSON API 錯誤 - 由於數據丟失,無法讀取數據。

[英]JSON API Error- The data couldn’t be read because it is missing.- in iOS, swift

我有 JSON 數據字符串結構,例如,

data: {
"items": [
    {
      "kind": "customsearch#result",
      "title": "XHAOYEAHX 40,60,110,150pcs Shoes Charms Fits ... - Amazon.com",
      "snippet": "Buy XHAOYEAHX 40, 60, 110, 150pcs Shoes Charms Fits for Croc Clog Shoes \nWristband Bracelet Party Girls Boys Gifts (Fixed Designs 100pcs) and other ...",
      "pagemap": {
        "scraped": [
          {
            "image_link": "https://images-na.ssl-images-amazon.com/images/I/91H%2BUO%2BMDQL._AC_UY395_.jpg"
          }
        ],
        "cse_image": [
          {
            "src": "https://images-na.ssl-images-amazon.com/images/I/91H%2BUO%2BMDQL._AC_UY395_.jpg"
          }
        ]
      }
    }
]}

我試圖將數據 model 結構稱為,

 struct Items: Codable {
        var title:String?
        var snippet:String?
        var pagemap : PageMap?
        enum CodingKeys: String, CodingKey {
            case title = "title"
            case snippet = "snippet"
            case pagemap = "pagemap"
        }
        init(from decoder: Decoder) throws {
               do {
                   let values = try decoder.container(keyedBy: CodingKeys.self)
                    title = try values.decode(String.self, forKey: .title)
                    snippet = try values.decode(String.self, forKey: .snippet)
                   pagemap = try values.decode(PageMap.self, forKey: .pagemap)
                  
               } catch {
                   print(error.localizedDescription)
               }
           }
    }
    struct PageMap: Codable {
        var cse_image: [Thumbnail]?
       private enum CodingKeys: String, CodingKey {
            case cse_image = "cse_image"
        }
        init(from decoder: Decoder) throws {
            do {
                let values = try decoder.container(keyedBy: CodingKeys.self)
                cse_image = try values.decode([Thumbnail].self, forKey: .cse_image)
               
            } catch {
                print(error.localizedDescription)
            }
        }
    }
    struct Thumbnail: Codable {
        let src: String?
        enum CodingKeys: String, CodingKey {
            case src = "src"
        }
        
    }

當我嘗試調用此結構並通過 dec.keyDecodingStrategy =.convertFromSnakeCase 從圖像的 src 字符串中獲取數據時,顯示無法讀取數據的錯誤,因為它丟失了,我哪里出錯了?

  let url = URL(string: "https://www.googleapis.com/customsearch/v1?q=shoes&key=myID&cx=ursearchID")!
       let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
           if let error = error {
               print("error: \(error)")
           } else {
               if let response = response as? HTTPURLResponse {
                   print("statusCode: \(response.statusCode)")
               }
            if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("data: \(dataString)")
              
              do{
                let jsonStr = dataString
                 let dec = JSONDecoder()
                    dec.keyDecodingStrategy = .convertFromSnakeCase
                 let res = try dec.decode(Data.self, from: jsonStr.data(using:.utf8)!)
              
                // self.items = [res]
                 for shop in res.items{
                    
                    self.shoptitle.append(shop.title!)
                    self.shopsnippet.append(shop.snippet!)
                     self.items.append(shop)
                    print(shop.snippet)
                    print(shop.pagemap?.cse_image)
                    if shop.pagemap?.cse_image != nil {
                        for info in (shop.pagemap?.cse_image!)! {
                        print(info.src)
                    }
                    }
                 }
                 
                 }
                 catch let error as NSError {
                     print("\(error)")
                 }
            }
           
              
           }
       }
       task.resume()

首先,您使用的Codable模型缺少 JSON 的根級別object 所以,你必須使用

struct Root: Codable {
    let items: [Items]
}

struct Items: Codable {
    let title:String?
    let snippet:String?
    let pagemap : PageMap?
}

struct PageMap: Codable {
    let cseImage: [Thumbnail]?
}

struct Thumbnail: Codable {
    let src: String?
}

重要的:

  1. 如果屬性名稱與JSON鍵完全匹配,則不需要enum CodingKeys
  2. 如果您不進行任何特定解析,則不需要init(from:)
  3. 不需要時不要使用var 在聲明屬性時使用let
  4. 如果在解析時使用convertFromSnakeCase ,則必須以駝峰形式創建屬性名稱(不帶下划線)。

接下來,您在URLSession中的解析代碼必須像 go 一樣,

URLSession.shared.dataTask(with: url) { (data, response, error) in
    if let data = data {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let res = try decoder.decode(Root.self, from: data)
        //rest of the code...
    }
}

這里有幾個錯誤:

  1. 當您已經擁有data時,您再次將jsonStr轉換為Data
  2. 如果您使用的是convertFromSnakeCase所有蛇形鍵將轉換為駝峰鍵,例如: cse_image -> cseImage
  3. Items , PageMap不需要自定義CodingKeysinit(from decoder: Decoder)
  4. 您的JSON更深一層,因此,您需要創建一個像這樣的邊界struct
struct Response: Decodable {
    var items: [Items]
}
  1. dec.decode(Data.self...嘗試解碼您需要嘗試解碼ResponseData類型。
try dec.decode(Response.self, from: data)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM