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

beq87vna  于 11个月前  发布在  iOS
关注(0)|答案(2)|浏览(161)

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

sshcrbum

sshcrbum1#

首先,您使用的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
1.如果你不做任何特定的解析,就不需要init(from:)
1.不需要时不要使用var。在声明属性时使用let
1.如果在解析时使用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...
    }
}

hjqgdpho

hjqgdpho2#

这里有几个错误:
1.当您已经有data时,您再次将jsonStr转换为Data
1.如果你使用的是convertFromSnakeCase,所有的蛇形键都将被转换为 Camel 键,例如:cse_image-> cseImage

  1. ItemsPageMap不需要自定义CodingKeysinit(from decoder: Decoder)
    1.你的JSON是一个更深的层次,所以,你需要创建一个边界struct像这样:
struct Response: Decodable {
    var items: [Items]
}

字符串

  1. dec.decode(Data.self...尝试解码Data类型你需要尝试解码Response
try dec.decode(Response.self, from: data)

相关问题