我有 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()
首先,您使用的
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?
}
重要:
JSON键完全匹配,则无需
enum CodingKeys
。init(from:)
。var
。在声明属性时使用 let
来代替。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...
}
}
这里有几个错误:
jsonStr
时,您将再次将 Data
转换为 data
。convertFromSnakeCase
,所有蛇形键都将转换为驼峰式键,例如:cse_image
-> cseImage
。Items
,PageMap
不需要自定义CodingKeys
或init(from decoder: Decoder)
。JSON
更深了一层,因此,您需要创建一个边界 struct
,如下所示:struct Response: Decodable {
var items: [Items]
}
dec.decode(Data.self...
尝试解码Data
类型您需要尝试解码Response
。try dec.decode(Response.self, from: data)