SwiftUI - 来自 GitHub REST API 的 JSON 无法解析

SwiftUI - JSON from GitHub REST API fails to parse

我正在尝试使用 GitHub 的 REST API 在 SwiftUI 中创建一个应用程序。我试图只检索给定用户的关注者的登录名和个人资料图片,然后填充 List.

FollowersView.swift

import SwiftUI

struct Follower: Codable, Hashable {
    public var login:      String
    public var avatar_url:  String
}

struct Response: Codable {
    var followers: [Follower] = [Follower]()
}

struct FollowersView: View {
    @EnvironmentObject var followerInfo: FollowerInfo
    @State var followers: [Follower] = [Follower]()
    
    init() {
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor.white]
    }
    
    var body: some View {
        NavigationView {
            ZStack {
                Color.black.edgesIgnoringSafeArea(.all)
                List(followers, id: \.self) { follower in
                    HStack(spacing: 10) {
                      Image(decorative: "\(follower.avatar_url).png")
                            .resizable()
                            .frame(width: 75, height: 75)
                        HStack(spacing: 5) {
                            Image(systemName: "person")
                            Text("\(follower.login)").fontWeight(.heavy)
                        }
                    }
                }
                .onAppear(perform: loadData)
            }
            .navigationBarTitle("\(followerInfo.followerUsername)")
        }
    }
    
    func loadData() {
        guard let url = URL(string: "https://api.github.com/users/\(followerInfo.followerUsername)/followers") else {
            print("Invalid URL")
            return
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    DispatchQueue.main.async {
                        self.followers = decodedResponse.followers
                    }
                    
                    return
                }
            }
            
            print("Fetch failed: \(error?.localizedDescription ?? "Unknown Error")")
        }.resume()
    }
}

struct FollowersView_Previews: PreviewProvider {
    static var previews: some View {
        FollowersView()
    }
}

代码到达 print("Fetch failed: \(error?.localizedDescription ?? "Unknown Error")") 并在崩溃前打印“未知错误”。检查返回的数据后,它什么也没有,至少我无法说出来。 (我并不完全习惯 Xcode 调试器)。我仔细检查了浏览器中的 API 响应,浏览器响应中的字段和 Codable 结构中的属性名称匹配。所以,我不确定这里发生了什么。关于如何解决这个问题有什么建议吗?

如果我没有正确理解你的问题。如下所示更新您的 Codable

import Foundation

// MARK: - FollowerElement
struct FollowerElement: Codable {
    let login: String
    let id: Int
    let nodeID: String
    let avatarURL: String
    let gravatarID: String
    let url, htmlURL, followersURL: String
    let followingURL, gistsURL, starredURL: String
    let subscriptionsURL, organizationsURL, reposURL: String
    let eventsURL: String
    let receivedEventsURL: String
    let type: String
    let siteAdmin: Bool

    enum CodingKeys: String, CodingKey {
        case login, id
        case nodeID = "node_id"
        case avatarURL = "avatar_url"
        case gravatarID = "gravatar_id"
        case url
        case htmlURL = "html_url"
        case followersURL = "followers_url"
        case followingURL = "following_url"
        case gistsURL = "gists_url"
        case starredURL = "starred_url"
        case subscriptionsURL = "subscriptions_url"
        case organizationsURL = "organizations_url"
        case reposURL = "repos_url"
        case eventsURL = "events_url"
        case receivedEventsURL = "received_events_url"
        case type
        case siteAdmin = "site_admin"
    }
}

typealias Follower = [FollowerElement]

您可以从上面的代码中删除不需要的属性。

现在更新您的 dataTask 方法

URLSession.shared.dataTask(with: request) { data, response, error in
        
        if let error = error {
            print("Fetch failed: \(error.localizedDescription)")
        } else {
            if let data = data {
                
                do {
                    let follower = try JSONDecoder().decode(Follower.self, from: data)
                        DispatchQueue.main.async {
                            print(follower.count)
                        }
                    
                } catch {
                    print(error)
                }
            }
        }
        
    }.resume()