【问题标题】:JSON API Error- The data couldn’t be read because it is missing.- in iOS, swiftJSON API 错误-由于缺少数据而无法读取数据。-在 iOS 中,swift
【发布时间】:2020-10-20 08:15:18
【问题描述】:

我有类似的 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()

【问题讨论】:

  • 你的 JSON 数据,不完美
  • 你的根对象肯定不是Data.self。在Codable 上下文中从不 print(error.localizedDescription)。仅打印 error 实例。而且结构中的大部分代码都是多余的。

标签: ios json swift iphone api


【解决方案1】:

这里有几个错误:

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

【讨论】:

    【解决方案2】:

    首先,您使用的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...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-08
      • 2016-10-30
      • 2020-12-11
      • 1970-01-01
      • 2020-09-21
      • 1970-01-01
      • 1970-01-01
      • 2020-11-20
      • 1970-01-01
      相关资源
      最近更新 更多