使用 JSON 对象中的键来解析数据并显示为列表

Use keys from JSON object to parse data and display as a list

我有一个 API returns 一个带有键的 JSON 对象: http://acnhapi.com/v1/bugs

既然不是数组,想知道怎么遍历。我正在尝试通过使用它们的键 common_butterflyyellow_butterfly

来获取错误名称“common butterfly”和“yellow butterfly”等的列表

我想显示 common_butterfly.name.name-USen 的值,但是对于每个错误。所以我的列表视图最终应该显示为:

(按字母顺序会更好)

数据

import SwiftUI

struct Bugs: Codable, Identifiable {
    let id = UUID()
    var name: String
}

class FetchBugs: ObservableObject {
  @Published var bugs = [Bugs]()
     
    init() {
        let url = URL(string: "http://acnhapi.com/v1/bugs")!
        URLSession.shared.dataTask(with: url) {(data, response, error) in
            do {
                if let bugsData = data {
                    let decodedData = try JSONDecoder().decode([Bugs].self, from: bugsData)
                    DispatchQueue.main.async {
                        self.bugs = decodedData
                    }
                } else {
                    print("No data")
                }
            } catch {
                print("Error")
            }
        }.resume()
    }
}

列表

import SwiftUI

struct BugList: View {
    @ObservedObject var fetch = FetchBugs()
    var body: some View {
        VStack {
            List(fetch.bugs) { bug in
                VStack(alignment: .leading) {
                    Text(bug.name)
                }
            }
        }
    }
}

struct BugList_Previews: PreviewProvider {
    static var previews: some View {
        BugList()
    }
}

这里有一个演示如何按字母顺序获取所有错误名称的 playground:

struct Bug: Decodable, Identifiable {
    let id: Int
    let name: Name

    struct Name: Decodable {
        let nameUSen: String

        enum CodingKeys: String, CodingKey {
            case nameUSen = "name-USen"
        }
    }
}

do {
    let butterflies = try Data(contentsOf: URL(string: "http://acnhapi.com/v1/bugs")!)
    let allBugs = try JSONDecoder().decode([String: Bug].self, from: butterflies)

    let bugs = Array(allBugs.values.sorted { [=10=].name.nameUSen < .name.nameUSen })
    bugs.forEach { print([=10=].name.nameUSen) }
} catch {
    print(error)
}

使用此解决方案,您可以解码所有本地化名称:

struct Bug: Decodable, Identifiable {
    enum CodingKeys: String, CodingKey { case name }
    
    let id = UUID()
    var localizedNames: [String: String] = [:]
    
    var nameUSen: String {
        localizedNames["name-USen"] ?? "error"
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let names = try container.decode([String: String].self, forKey: .name)
        for (key, value) in names {
            localizedNames[key] = value
        }
    }
}

使用.sorted { [=14=].nameUSen < .nameUSen }对您的数据排序

class FetchBugs: ObservableObject {
    @Published var bugs = [Bug]()

    init() {
        let url = URL(string: "http://acnhapi.com/v1/bugs")!
        URLSession.shared.dataTask(with: url) { data, response, error in
            do {
                if let bugsData = data {
                    let decodedData = try JSONDecoder().decode([String: Bug].self, from: bugsData)
                    DispatchQueue.main.async {
                        self.bugs = Array(decodedData.values).sorted { [=11=].nameUSen < .nameUSen }
                    }
                } else {
                    print("No data")
                }
            } catch {
                print(error)
            }
        }.resume()
    }
}

并显示 USen 姓名:

struct BugList: View {
    @ObservedObject var fetch = FetchBugs()
    var body: some View {
        VStack {
            List(fetch.bugs) { bug in
                VStack(alignment: .leading) {
                    Text(bug.nameUSen)
                }
            }
        }
    }
}

如果您想访问任何其他名称,您可以使用:

bug.localizedNames["name-EUde"]!