【发布时间】:2021-01-29 13:27:23
【问题描述】:
我正在尝试从 Google 的 Book API 获得响应。在那里我可以得到响应,但例如,在某些书中有description 或许多其他键响应JSON。如果我根据描述键设计我的结构,其他没有描述的书籍给了我 dataCorrupted 错误并且没有解码 JSON。如果我不这样做,我会在其他有描述的书中得到同样的错误。我希望我能解释一下自己。如何正确解决?
这是我的根类可编码:
import Foundation
struct RootClass : Codable {
let items : [Item]?
let kind : String?
let totalItems : Int?
enum CodingKeys: String, CodingKey {
case items = "items"
case kind = "kind"
case totalItems = "totalItems"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
items = try values.decodeIfPresent([Item].self, forKey: .items)
kind = try values.decodeIfPresent(String.self, forKey: .kind)
totalItems = try values.decodeIfPresent(Int.self, forKey: .totalItems)
}
}
我需要到达 root -> items -> volumeInfo。
这里是 Item 可编码结构:
import Foundation
struct Item : Codable {
let accessInfo : AccessInfo?
let etag : String?
let id : String?
let kind : String?
let saleInfo : SaleInfo?
let searchInfo : SearchInfo?
let selfLink : String?
let volumeInfo : VolumeInfo?
enum CodingKeys: String, CodingKey {
case accessInfo = "accessInfo"
case etag = "etag"
case id = "id"
case kind = "kind"
case saleInfo = "saleInfo"
case searchInfo = "searchInfo"
case selfLink = "selfLink"
case volumeInfo = "volumeInfo"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
accessInfo = try AccessInfo(from: decoder)
etag = try values.decodeIfPresent(String.self, forKey: .etag)
id = try values.decodeIfPresent(String.self, forKey: .id)
kind = try values.decodeIfPresent(String.self, forKey: .kind)
saleInfo = try SaleInfo(from: decoder)
searchInfo = try SearchInfo(from: decoder)
selfLink = try values.decodeIfPresent(String.self, forKey: .selfLink)
volumeInfo = try VolumeInfo(from: decoder)
}
}
我在这里解析 json:
func parseJSON(searchData: Data) -> [SearchedModel]?{
let decode = JSONDecoder()
do{
let decodedData = try decode.decode(RootClass.self, from: searchData)
// IN HERE I CAN USE FOR LOOP TO ITEMS AND GET VOLUME INFO DATAS BUT ITS ALL NIL
return mainDataArr
}catch{
print(error)
return nil
}
}
当我尝试循环访问项目并获取卷信息数据时,它全部为零。我不明白为什么这一切都是零?我该如何解决?
这里是 JSON 1 的一部分:
"kind": "books#volumes",
"totalItems": 1196,
"items": [
{
"kind": "books#volume",
"id": "4qnmsgEACAAJ",
"etag": "dYXW8bT6JB0",
"selfLink": "https://www.googleapis.com/books/v1/volumes/4qnmsgEACAAJ",
"volumeInfo": {
"title": "Sineklerin Tanrisi",
"authors": [
"William Golding"
],
"publishedDate": "2014-01-01",
"industryIdentifiers": [
{
"type": "ISBN_10",
"identifier": "9754582904"
},
{
"type": "ISBN_13",
"identifier": "9789754582901"
}
],
"readingModes": {
"text": false,
"image": false
},
"pageCount": 261,
"printType": "BOOK",
"categories": [
"Boys"
],
"maturityRating": "NOT_MATURE",
"allowAnonLogging": false,
"contentVersion": "preview-1.0.0",
"imageLinks": {
"smallThumbnail": "http://books.google.com/books/content?id=4qnmsgEACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api",
"thumbnail": "http://books.google.com/books/content?id=4qnmsgEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
},
"language": "tr",
"previewLink": "http://books.google.com.tr/books?id=4qnmsgEACAAJ&dq=sineklerin+tanrisi&hl=&cd=1&source=gbs_api",
"infoLink": "http://books.google.com.tr/books?id=4qnmsgEACAAJ&dq=sineklerin+tanrisi&hl=&source=gbs_api",
"canonicalVolumeLink": "https://books.google.com/books/about/Sineklerin_Tanrisi.html?hl=&id=4qnmsgEACAAJ"
},
"saleInfo": {
"country": "TR",
"saleability": "NOT_FOR_SALE",
"isEbook": false
},
"accessInfo": {
"country": "TR",
"viewability": "NO_PAGES",
"embeddable": false,
"publicDomain": false,
"textToSpeechPermission": "ALLOWED",
"epub": {
"isAvailable": false
},
"pdf": {
"isAvailable": false
},
"webReaderLink": "http://play.google.com/books/reader?id=4qnmsgEACAAJ&hl=&printsec=frontcover&source=gbs_api",
"accessViewStatus": "NONE",
"quoteSharingAllowed": false
}
}
这里是 JSON 2(具有相同的请求响应):
"kind": "books#volumes",
"totalItems": 432,
"items": [
{
"kind": "books#volume",
"id": "yodWha1LmPsC",
"etag": "2bZz2CDqiq4",
"selfLink": "https://www.googleapis.com/books/v1/volumes/yodWha1LmPsC",
"volumeInfo": {
"title": "Momo the Monkey Arrives",
"authors": [
"Shariffa Keshavjee"
],
"publisher": "Master Publishing",
"publishedDate": "2012-09-21",
"description": "Momo the Monkey Arrives is the first in a series of illustrated children's books about the rescue of a monkey and how his presence livens up the household of two children: a boy and a girl. Along the way, as they take care of Momo, Geno and Alid learn how to give the best possible care to a monkey like him, and how to be more responsible children. The adventures of Momo are based on a true story.",
"industryIdentifiers": [
{
"type": "ISBN_13",
"identifier": "9789966158987"
},
{
"type": "ISBN_10",
"identifier": "9966158987"
}
],
"readingModes": {
"text": true,
"image": true
},
"pageCount": 28,
"printType": "BOOK",
"categories": [
"Juvenile Fiction"
],
"maturityRating": "NOT_MATURE",
"allowAnonLogging": false,
"contentVersion": "1.4.4.0.preview.3",
"panelizationSummary": {
"containsEpubBubbles": false,
"containsImageBubbles": false
},
"imageLinks": {
"smallThumbnail": "http://books.google.com/books/content?id=yodWha1LmPsC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
"thumbnail": "http://books.google.com/books/content?id=yodWha1LmPsC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
},
"language": "en",
"previewLink": "http://books.google.com.tr/books?id=yodWha1LmPsC&pg=PT25&dq=momo&hl=&cd=1&source=gbs_api",
"infoLink": "https://play.google.com/store/books/details?id=yodWha1LmPsC&source=gbs_api",
"canonicalVolumeLink": "https://play.google.com/store/books/details?id=yodWha1LmPsC"
},
"saleInfo": {
"country": "TR",
"saleability": "FOR_SALE",
"isEbook": true,
"listPrice": {
"amount": 35.04,
"currencyCode": "TRY"
},
"retailPrice": {
"amount": 35.04,
"currencyCode": "TRY"
},
"buyLink": "https://play.google.com/store/books/details?id=yodWha1LmPsC&rdid=book-yodWha1LmPsC&rdot=1&source=gbs_api",
"offers": [
{
"finskyOfferType": 1,
"listPrice": {
"amountInMicros": 35040000,
"currencyCode": "TRY"
},
"retailPrice": {
"amountInMicros": 35040000,
"currencyCode": "TRY"
}
}
]
},
"accessInfo": {
"country": "TR",
"viewability": "PARTIAL",
"embeddable": true,
"publicDomain": false,
"textToSpeechPermission": "ALLOWED",
"epub": {
"isAvailable": true
},
"pdf": {
"isAvailable": true
},
"webReaderLink": "http://play.google.com/books/reader?id=yodWha1LmPsC&hl=&printsec=frontcover&source=gbs_api",
"accessViewStatus": "SAMPLE",
"quoteSharingAllowed": false
},
"searchInfo": {
"textSnippet": "<b>Momo</b> the Monkey Adventure Series <b>Momo</b> the Monkey Arrives <b>Momo</b> Makes a <br>\nMess <b>Momo</b> Comes to the Rescue <b>Momo</b> Moves to the Orphanage Look out for <br>\nthese stories about <b>Momo</b> and his friends. More coming soon! Master Publishing<br>\n ..."
}
}
【问题讨论】:
-
如果需要,可以选择属性(可以是 nil/null),如果 JSON 中不存在密钥,则使用自定义
init(from decoder:)并使用decodeIfPresent() -
在 decodeIfPresent 中,我得到 JsonDecoder has no member decodeIfPresent 错误。
-
我的所有属性都是可选的。
-
developer.apple.com/documentation/swift/… 应该在那里。我用过它(我不是唯一一个)。但是代码和具有两个可能版本(一个有键/值,一个没有键/值)的可复制 JSON 会有所帮助。