Swift JSON嵌套的ListView输出



我试图显示结果的内容。数据作为JSON数组返回。我创建了一个视图模型"股票"并且想要访问"结果"。当前正在编译,但数据没有显示。

非常感谢您的帮助

import SwiftUI
struct Stocks: Hashable, Codable{
var results: [Results]
var status: String

struct Results: Hashable, Codable{
var ticker: String
var name: String
var market: String
var locale: String
var primary_exchange: String
var type: String
var active: Bool
var currency_name: String
var cik: String
var composite_figi: String
var share_class_figi: String
var last_update_utc: String
}
}

class ViewModel: ObservableObject{
@Published var stocks: [Stocks] = []
func fetch(){
guard let url = URL(string: "https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&apiKey=<apikey>") else{return}

let task = URLSession.shared.dataTask(with: url) {[weak self]data, _, error in
guard let data = data, error == nil else{
return
}
// Convert JSON
do{
let stocks = try JSONDecoder().decode([Stocks].self, from: data)
DispatchQueue.main.async{
self?.stocks = stocks
}

}
catch{
print(error)
}
}
task.resume()
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()

var body: some View {
NavigationView{
List{
ForEach(viewModel.stocks, id: .self){resu in
ForEach(resu.results, id: .self){st in
Text(st.currency_name)
}
}

}
}.navigationTitle("Stocks")
.onAppear{
viewModel.fetch()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

下面是响应对象:

{
"results": [
{
"ticker": "A",
"name": "Agilent Technologies Inc.",
"market": "stocks",
"locale": "us",
"primary_exchange": "XNYS",
"type": "CS",
"active": true,
"currency_name": "usd",
"cik": "0001090872",
"composite_figi": "BBG000C2V3D6",
"share_class_figi": "BBG001SCTQY4",
"last_updated_utc": "2022-12-20T00:00:00Z"
},
{
"ticker": "AA",
"name": "Alcoa Corporation",
"market": "stocks",
"locale": "us",
"primary_exchange": "XNYS",
"type": "CS",
"active": true,
"currency_name": "usd",
"cik": "0001675149",
"composite_figi": "BBG00B3T3HD3",
"share_class_figi": "BBG00B3T3HF1",
"last_updated_utc": "2022-12-20T00:00:00Z"
},

我创建了一个视图模型" stock "并且想要访问"结果"。当前正在编译,但数据没有显示。

结构的命名很容易混淆。

根据JSON,您将收到一个根对象,包含键resultsStock(假定以单数形式命名)对象数组。

并且存在一个与键last_updated_utc不匹配的结构成员last_update_utc

以这种方式命名您的结构体,我将结构体成员重命名为camelCase和常量(let),您可以使用.iso8601策略将lastUpdatedUtc解码为Date

struct Response: Hashable, Decodable {
let results: [Stock]
let status: String

struct Stock: Hashable, Decodable {
let ticker: String
let name: String
let market: String
let locale: String
let primaryExchange: String
let type: String
let active: Bool
let currencyName: String
let cik: String
let compositeFigi: String
let shareClassFigi: String
let lastUpdatedUtc: Date
}
}

并解码JSON

class ViewModel: ObservableObject{
@Published var stocks: [Response.Stock] = []
func fetch() {
guard let url = URL(string: "https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&apiKey=<apikey>") else{return}

let task = URLSession.shared.dataTask(with: url) {[weak self] data, _, error in
if let error { print(error); return }
// Convert JSON
do{
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601
let response = try decoder.decode(Response.self, from: data!)
DispatchQueue.main.async {
self?.stocks = response.results
}

}
catch{
print(error)
}
}
task.resume()
}
}
我甚至建议使用async/await
@MainActor
class ViewModel: ObservableObject{
@Published var stocks: [Response.Stock] = []

func fetch() {
guard let url = URL(string: "https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&apiKey=<apikey>") else{return}
Task {
do {
let (data, _) = try await URLSession.shared.data(from: url)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601
let response = try decoder.decode(Response.self, from: data)
self.stocks = response.results
} catch {
print(error)
}
}
}
}

最新更新