JSON API 错误- 无法读取数据,因为它丢失了。- 在 iOS、swift 中

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"
          }
        ]
      }
    }
]}

我尝试将数据模型结构称为 ,

 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()

这里有几个错误:

  1. 当您已经 data.
  2. 时,您再次将 jsonStr 转换为 Data
  3. 如果您使用 convertFromSnakeCase,所有蛇形键都将转换为驼峰键,例如:cse_image -> cseImage.
  4. ItemsPageMap 不需要自定义 CodingKeysinit(from decoder: Decoder).
  5. 您的 JSON 更深一层,因此,您需要像这样创建边界 struct
struct Response: Decodable {
    var items: [Items]
}
  1. dec.decode(Data.self... 尝试解码 Data 您需要尝试解码的类型 Response.
try dec.decode(Response.self, from: data)

首先,您正在使用的 Codable 模型缺少 JSON 的根级对象。所以,你必须使用

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,则必须在 camel-case(不带下划线)中创建 属性 名称。

接下来,你在URLSession中的解析代码必须是这样的,

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...
    }
}