可解码的SWIFT解析REST API数据错误

bqf10yzr  于 2022-09-19  发布在  Swift
关注(0)|答案(1)|浏览(141)

我正在尝试查询Marvel API。我想我的解码器是错的。我有以下代码:

struct ReturnedData : Decodable {

    var id : Int?
    var name : String?
    var description : String?
}

var savedData : [ReturnedData] = []

    let urlString = "https://gateway.marvel.com/v1/public/characters?ts=1&apikey=(myAPIKey)"
    let url = URL(string: urlString)
    let session = URLSession.shared

    let dataTask = session.dataTask(with: url!) { (data, response, error) in
        guard let data = data else {return}
        do {
            let recievedData = try JSONDecoder().decode([ReturnedData].self, from: data)
            self.savedData = recievedData
        } catch {
            print(error)
        }
    }
    dataTask.resume()
}

我收到以下错误消息:typeMisMatch(Swift.Array,Swift.DecodingError.Context(codingPath:[],debugDescription:“期望对数组进行解码,但找到了字典。”,underlyingError:nil))

根据文档,我应该得到以下所有内容:

id(int,可选):角色资源的唯一ID,name(字符串,可选):角色名称。Description(字符串,可选):对角色的简短简介或描述。修改日期(日期,可选):资源最近一次修改的日期。resource URI(字符串,可选):该资源的规范URL标识。URL(数组[URL],可选):资源的公共网站URL集合。缩略图(图片,可选):该角色的代表性图片。漫画(ComicList,可选):包含该角色漫画的资源列表。Stories(故事列表,可选):该角色出现的故事资源列表Events(EventList,可选):该角色出现的事件资源列表。系列(SeriesList,可选):该字符出现的系列资源列表。

此外,任何关于如何获得缩略图的提示都是值得赞赏的。

sczxawaw

sczxawaw1#

您得到的错误是因为您拥有的模型与json数据不匹配。因此,尝试这种方法...to query the marvel API...。将来,将您的json数据复制并粘贴到https://app.quicktype.io/中,这将为您生成模型。根据您的需要调整生成的代码。或者,在https://developer.marvel.com/docs#!/public/getCreatorCollection_get_0上阅读文档,并根据给定的信息手动创建模型。

class MarvelModel: ObservableObject {
    @Published var results = [MarvelResult]()

    let myAPIKey = "xxxx"
    let myhash = "xxxx"

    func getMarvels() async {
        guard let url = URL(string: "https://gateway.marvel.com/v1/public/characters?ts=1&apikey=(myAPIKey)&hash=(myhash)") else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let response = try JSONDecoder().decode(MarvelResponse.self, from: data)
            Task{@MainActor in
                results = response.data.results
            }
        } catch {
            print("---> error: (error)")
        }
    }
}

struct ContentView: View {
    @StateObject var vm = MarvelModel()

    var body: some View {
        VStack {
            if vm.results.isEmpty { ProgressView() }
            List(vm.results) { item in
                Text(item.name)
            }
        }
        .task {
            await vm.getMarvels()
        }
    }
}

struct MarvelResponse: Decodable {
    let code: Int
    let status, copyright, attributionText, attributionHTML: String
    let etag: String
    let data: MarvelData
}

struct MarvelData: Decodable {
    let offset, limit, total, count: Int
    let results: [MarvelResult]
}

struct MarvelResult: Identifiable, Decodable {
    let id: Int
    let name, resultDescription: String
    let modified: String
    let thumbnail: Thumbnail
    let resourceURI: String
    let comics, series: Comics
    let stories: Stories
    let events: Comics
    let urls: [URLElement]

    enum CodingKeys: String, CodingKey {
        case id, name
        case resultDescription = "description"
        case modified, thumbnail, resourceURI, comics, series, stories, events, urls
    }
}

struct Comics: Decodable {
    let available: Int
    let collectionURI: String
    let items: [ComicsItem]
    let returned: Int
}

struct ComicsItem: Identifiable, Decodable {
    let id = UUID()
    let resourceURI: String
    let name: String
}

struct Stories: Decodable {
    let available: Int
    let collectionURI: String
    let items: [StoriesItem]
    let returned: Int
}

struct StoriesItem: Identifiable, Decodable {
    let id = UUID()
    let resourceURI: String
    let name: String
    let type: String
}

struct Thumbnail: Decodable {
    let path: String
    let thumbnailExtension: String

    enum CodingKeys: String, CodingKey {
        case path
        case thumbnailExtension = "extension"
    }
}

struct URLElement: Identifiable, Decodable {
    let id = UUID()
    let type: String
    let url: String
}

编辑-1:如果你想要一些非常基本的东西,那么试试这个:

struct ContentView: View {
    @State var results = [MarvelResult]()

    var body: some View {
        List(results) { item in
            Text(item.name)
        }
        .onAppear {
            getMarvels()
        }
    }

    func getMarvels() {
        let myAPIKey = "xxxx"
        let myhash = "xxxx"
        guard let url = URL(string: "https://gateway.marvel.com/v1/public/characters?ts=1&apikey=(myAPIKey)&hash=(myhash)") else { return }
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            if let data = data {
                do {
                    let response = try JSONDecoder().decode(MarvelResponse.self, from: data)
                    DispatchQueue.main.async {
                        self.results = response.data.results
                    }
                }
                catch {
                    print(error)
                }
            }
        }.resume()
    }
}

相关问题