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

问题描述 投票:0回答:2

我有 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()
ios json swift
2个回答
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...
    }
}

0
投票

这里有几个错误:

  1. 当您已经拥有
    jsonStr
    时,您将再次将
    Data
    转换为
    data
  2. 如果您使用
    convertFromSnakeCase
    ,所有蛇形键都将转换为驼峰式键,例如:
    cse_image
    ->
    cseImage
  3. Items
    PageMap
    不需要自定义
    CodingKeys
    init(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)
© www.soinside.com 2019 - 2024. All rights reserved.