【发布时间】:2021-09-29 08:51:22
【问题描述】:
我在尝试从 MTA API(纽约地铁系统)(Link Here)获取数据返回时遇到了一些麻烦。数据在 GTFS 中,所以我使用了一个在虚拟环境中设置的解析器,它将数据转换为 JSON 并将其发送给我(示例 JSON 稍后发布)。基本完成了GTFS到JSON的解码。
现在我有了 JSON 数据,我需要让它显示在我的应用程序中。我以前处理过 API,但没有一个具有这么多“层”的 API。
问题是:我应该如何在 Swift 端构建我的代码,以便我可以访问在 JSON 中发送的每个数据点?
以下是我的工作。数据根本没有显示在我的 ContentView 中。我猜这与我的模型结构不正确有关,因此我试图显示的数据实际上并不存在:
struct TrainResponse: Codable {
let data: [String]
let n, s: [NS]
let id: String
let lastUpdate: Date
let location: [Double]
let name: String
let routes: [String]
let stops: [String: [Double]]
enum CodingKeys: String, CodingKey {
case data
case n = "N"
case s = "S"
case id
case lastUpdate = "last_update"
case location, name, routes, stops
}
}
// MARK: - N
struct NS: Codable {
let route: String
let time: Date
}
class API: ObservableObject {
@Published var storedData = String()
@Published var ns = NS.self
@Published var id = String()
@Published var lastUpdate = Date()
@Published var location = [Double]()
@Published var name = String()
@Published var routes = [String]()
@Published var stops = [String: [Double]]()
func loadData() {
guard let url = URL(string: "http://127.0.0.1:5000/by-route/A") else {
print("Your API end point is Invalid")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
if let response = try? JSONDecoder().decode(TrainResponse.self, from: data) {
DispatchQueue.main.async {
if let data = response.data.first {
self.storedData = data
self.routes = response.routes
self.id = response.id
self.lastUpdate = response.lastUpdate
self.location = response.location
self.name = response.name
self.routes = response.routes
self.stops = response.stops
}
}
return
}
}
}.resume()
}
}
以下是 JSON 的示例 - 它重复了您在下面看到的数百次,但我在示例中将其关闭,就好像它是一个完整的 JSON 对象一样(以便更容易调试)
{
"data": [
{
"N": [
{
"route": "A",
"time": "2021-07-21T21:33:00-04:00"
}
],
"S": [
{
"route": "A",
"time": "2021-07-21T21:34:40-04:00"
}
],
"id": "6d6a",
"last_update": "2021-07-21T21:25:06-04:00",
"location": [
40.681711,
-73.837683
],
"name": "104 St",
"routes": [
"A"
],
"stops": {
"A63": [
40.681711,
-73.837683
]
}
}
],
"updated": "2021-07-21T21:25:06-04:00"
}
在这里我真的束手无策。关于如何重组我的代码以正确返回数据的任何想法?
我知道我应该嵌套数据(例如self.routes = data["N"].etc.etc,但我似乎不太清楚如何构建我的代码,所以我可以这样做。一旦完成,我应该可以轻松显示数据在应用中.. 只需先将数据导入应用即可!
编辑 - 为内容视图添加代码
import SwiftUI
struct ContentView: View {
@StateObject var api = API()
var body: some View {
Text("yo")
List {
ForEach(api.routes, id: \.self) { index in
Text(index)
}
}
.onAppear { api.loadData() }
}
}
EDIT 2 我已经更新了数据模型。它们现在如下所示:
struct Main: Codable {
let data: [Datum]
let updated: String
}
// MARK: - Datum
struct Datum: Codable {
let n, s: [N]
let id: String
let lastUpdate: Date
let location: [Double]
let name: String
let routes: [String]
let stops: [String: [Double]]
enum CodingKeys: String, CodingKey {
case n = "N"
case s = "S"
case id
case lastUpdate = "last_update"
case location, name, routes, stops
}
}
// MARK: - N
struct N: Codable {
let route: String
let time: Date
}
【问题讨论】:
-
看看quicktype.io,它可以帮助您了解您的结构可能遗漏的内容。
-
那是我最初用来生成结构的。我对其进行了一些更改,因为它没有考虑 JSON 中的初始“数据:”部分。你认为 QuickType 结构是完全正确的吗?
-
能否展示用于在 ContentView 中显示数据的代码。 swift/apple 也只喜欢“https”
-
@workingdog 我已将代码添加到帖子中。这很简单,因为我想在开始构建视图之前确认我可以让数据返回。
-
你从你的服务器上得到了什么。如果在“URLSession.shared.dataTask(...)”之后添加“print(”\n--------> data:(data) error:(error)\n")”。你得到了什么?没有端点连接很难调试。