你好,我叫妮可,
我是 App 編程/SwiftUI 的完全初學者。我正在嘗試從 Web api 決議 json 資料,但不知何故我無法正確決議資料。我假設我的 json 結構不正確,但我找不到問題。
我從 Web API 得到的 Json 看起來像這樣:
{
"pois": [
{
"id": "2635094451",
"lat": "52.410150",
"lat_s": "52.4",
"lng": "10.776630",
"lng_s": "10.8",
"street": "R?ntgenstra?e",
"content": "8137285512",
"backend": "0-239283152",
"type": "1",
"vmax": "50",
"counter": "0",
"create_date": "2021-11-18 13:21:50",
"confirm_date": "2021-11-18 13:21:43",
"gps_status": "-",
"info": " {\"qltyCountryRoad\":1,\"confirmed\":\"0\",\"gesperrt\":\"0\",\"precheck\":\"[Q1|21|0]\"}",
"polyline": ""
}
],
"grid": []
}
我的結構如下所示:
struct APIResponse: Codable {
let pois: [InputDataPois]
let grid: [InputDataGrid]
private enum CodingKeys: String, CodingKey {
case pois
case grid
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.pois = try container.decode(APIResponse.self, forKey: .pois).pois
self.grid = try container.decode(APIResponse.self, forKey: .grid).grid
}
}
struct InputDataPois: Codable, Identifiable {
let id:String
let lat:String
let lat_s:String
let lng:String
let lng_s:String
let street:String
let content:String
let backend:String
let type:String
let vmax:String
let counter:String
let create_date:String
let confirm_date:String
let gps_status:String
let info:String
let polyline:String
}
extension InputDataPois {
private enum CodingKeys: String, CodingKey {
case id
case lat
case lat_s
case lng
case lng_s
case street
case content
case backend
case type
case vmax
case counter
case create_date
case confirm_date
case gps_status
case info
case polyline
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.lat = try container.decode(String.self, forKey: .lat)
self.lat_s = try container.decode(String.self, forKey: .lat_s)
self.lng = try container.decode(String.self, forKey: .lng)
self.lng_s = try container.decode(String.self, forKey: .lng_s)
self.street = try container.decode(String.self, forKey: .street)
self.content = try container.decode(String.self, forKey: .content)
self.backend = try container.decode(String.self, forKey: .backend)
self.type = try container.decode(String.self, forKey: .type)
self.vmax = try container.decode(String.self, forKey: .vmax)
self.counter = try container.decode(String.self, forKey: .counter)
self.create_date = try container.decode(String.self, forKey: .create_date)
self.confirm_date = try container.decode(String.self, forKey: .confirm_date)
self.gps_status = try container.decode(String.self, forKey: .gps_status)
self.info = try container.decode(String.self, forKey: .info)
self.polyline = try container.decode(String.self, forKey: .polyline)
}
}
struct InputDataGrid: Codable {
}
我的捆綁包是這樣的:
extension Bundle {
func decode(_ file: String) -> [InputDataPois] {
// 1. Locate the Json File
guard let url = URL(string: file) else {
fatalError("Failed to locate \(file) in bundle")
}
// 2.Create a property for the Data
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to Load \(file) from bundle.")
}
// 3. Create a property for the data
let str = String(decoding: data, as: UTF8.self)
print("\(str)")
guard let loaded = try? JSONDecoder().decode(APIResponse.self, from: data).pois else {
fatalError("Failed to decode \(file) from bundle.")
}
// 4. Return the ready-to-use data
return loaded
}
}
在我看來,我正在使用:
let speed: [InputDataPois] = Bundle.main.decode("https://cdn2.atudo.net/api/1.0/vl.php?type=0,1,2,3,4,5,6&box=52.36176390234046,10.588760375976562,52.466468685912744,11.159706115722656")
我得到的錯誤看起來像這樣。
錯誤訊息 控制臺錯誤
預先感謝您的幫助。
uj5u.com熱心網友回復:
洗掉您的自定義 Codable 實作和編碼鍵。它們不是必需的,編譯器可以使用這個簡單的 JSON 為您生成它們。那么一切都應該有效。
這里的問題特別是你的 APIResponse 解碼:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.pois = try container.decode(APIResponse.self, forKey: .pois).pois
self.grid = try container.decode(APIResponse.self, forKey: .grid).grid
}
要解碼 APIResponse,您可以嘗試解碼兩個 APIResponse。這將再次嘗試解碼導致無限遞回的 APIResponse。您沒有看到的唯一原因是您的 JSON 包含使第二次呼叫container(keyedBy:)失敗的陣列。嘗試在你的第一行設定一個斷點(或者如果你必須設定一個列印陳述句)init(from:),你會看到它在失敗之前被第二次呼叫。
要解決此問題,您需要解碼屬性的實際型別:
self.pois = try container.decode([InputDataPois].self, forKey: .pois)
但是正如我所說,您的 JSON 格式中沒有任何內容需要手動實作解碼器,因此最好讓編譯器為您合成。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/372533.html
