swift 解码错误:typeMismatch,解码来自Rest API(VBB)的数据时

ghhkc1vu  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(141)

我正尝试使用此方法从Rest API检索JSON。

import Foundation
import Combine
import SwiftUI

class JsonDataVBB: ObservableObject {
@Published var stationNameAPI = [StopLocation]()

    func departureNEWOldFetch() {
         let url = URL(string: "https://....")!
         URLSession.shared.dataTask(with: url) { (data, response, error) in
             if let error = error {
                 print("Error fetching departures: \(error)")
                 return
             }
             guard let data = data else {
                 print("No data received")
                 return
             }
             do {
                 let sucheVBB = try JSONDecoder().decode([StopLocation].self, from: data)
                 DispatchQueue.main.async {
                     self.stationNameAPI = sucheVBB
    
                 }
             } catch let error {
                 print("Error decoding departures: \(error)")
             }
         }.resume()
     }

}

为此,我创建了一个Swift解码模型,用它来解码Json:(使用应用程序快速输入...)

import Foundation

// MARK: - StationLocal
struct StationSuche: Codable, Identifiable {
    var id = UUID()
    let stopLocationOrCoordLocation: [StopLocationOrCoordLocation]
    let technicalMessages: TechnicalMessages
    let serverVersion, dialectVersion, requestID: String

    enum CodingKeys: String, CodingKey {
        case stopLocationOrCoordLocation
        case technicalMessages
        case serverVersion, dialectVersion
        case requestID
    }
}

// MARK: - StopLocationOrCoordLocation
struct StopLocationOrCoordLocation: Codable {
    let stopLocation: StopLocation

    enum CodingKeys: String, CodingKey {
        case stopLocation
    }
}

// MARK: - StopLocation
struct StopLocation: Codable {
    let locationNotes: LocationNotes
    let altID: [String]
    let timezoneOffset: Int
    let id, extID, name: String
    let lon, lat: Double
    let weight, products: Int

    enum CodingKeys: String, CodingKey {
        case locationNotes
        case altID
        case timezoneOffset, id
        case extID
        case name, lon, lat, weight, products
    }
}

// MARK: - LocationNotes
struct LocationNotes: Codable {
    let locationNote: [LocationNote]

    enum CodingKeys: String, CodingKey {
        case locationNote
    }
}

// MARK: - LocationNote
struct LocationNote: Codable {
    let value, key, type, txtN: String
}

// MARK: - TechnicalMessages
struct TechnicalMessages: Codable {
    let technicalMessage: [TechnicalMessage]

    enum CodingKeys: String, CodingKey {
        case technicalMessage
    }
}

// MARK: - TechnicalMessage
struct TechnicalMessage: Codable {
    let value, key: String
}

我在视图中进行查询:

import SwiftUI

struct TestTABTESTTEST: View {
    @ObservedObject var jsonDataVBB = JsonDataVBB()
    var body: some View {
        NavigationView {
            VStack {
                List {
             //(here i need help also, with for each)
                }
                .navigationBarTitle("⚠", displayMode: .inline)
                .onAppear{
                    jsonDataVBB.departureNEWOldFetch()
                }
                .refreshable {
                    jsonDataVBB.departureNEWOldFetch()
                }
            }
            .toolbarBackground(.visible, for: .navigationBar)

            
        }
        .toolbarBackground(.visible, for: .navigationBar)
        .toolbarBackground(.visible, for: .tabBar)
        .toolbarBackground(.visible, for: .bottomBar)
        .toolbarBackground(.visible, for: .navigationBar)
        
    }
}
struct TestTABTESTTEST_Previews: PreviewProvider {
    static var previews: some View {
        TestTABTESTTEST()
    }
}

我的问题是,每当我显示视图并因此执行查询时,我都会得到错误:

Error decoding departures: typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

下面是JSON文件(从服务器返回的内容)

HIDDEN

我已经看了各种教程,也玩了一点ChatGPT,我仍然是相当新的解码和Swift用户界面中的Json,与本地(在Bundle.main ...)Json我已经走了很远,也与轻查询,但在这里我做我很难,我现在决定后,永恒的摆弄只是问这里的社区。
我也通读了其他帖子,但不幸的是他们没能帮助我...

bjp0bcyl

bjp0bcyl1#

试试这个例子代码来获取,解码和显示你的json数据。2重要的是要记住你的模型需要和json数据完全匹配。
您必须参考服务器文档来确定哪些属性是可选的,并通过添加?来调整模型的代码。

struct ContentView: View {
    var body: some View {
        TestTABTESTTEST()
    }
}

struct TestTABTESTTEST: View {
    @StateObject var jsonDataVBB = JsonDataVBB()  // <-- here
    
    var body: some View {
        NavigationView {
            VStack {
                // --- here
                List(jsonDataVBB.stationNameAPI) { item in
                    Text(item.name).foregroundColor(.blue)
                    Text("lat: \(item.lat)  lon: \(item.lon)")
                }
                .navigationBarTitle("⚠", displayMode: .inline)
                .onAppear{
                    jsonDataVBB.departureNEWOldFetch()
                }
                .refreshable {
                    jsonDataVBB.departureNEWOldFetch()
                }
            }
            .toolbarBackground(.visible, for: .navigationBar)
        }
        .toolbarBackground(.visible, for: .navigationBar)
        .toolbarBackground(.visible, for: .tabBar)
        .toolbarBackground(.visible, for: .bottomBar)
        .toolbarBackground(.visible, for: .navigationBar)
    }
}

class JsonDataVBB: ObservableObject {
    @Published var stationNameAPI = [StopLocation]()
    
    func departureNEWOldFetch() {
        let url = URL(string: "https://....")!
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            if let error = error {
                print("Error fetching departures: \(error)")
                return
            }
            guard let data = data else {
                print("No data received")
                return
            }
            do {
                // --- here
                let sucheVBB = try JSONDecoder().decode(StationSuche.self, from: data)
                DispatchQueue.main.async {
                    // --- here
                    self.stationNameAPI = sucheVBB.stopLocationOrCoordLocation.map{$0.stopLocation}
                }
            } catch let error {
                print("Error decoding departures: \(error)")
            }
        }.resume()
    }
    
}

struct StationSuche: Codable, Identifiable {
    var id = UUID()
    let stopLocationOrCoordLocation: [StopLocationOrCoordLocation]
    let technicalMessages: TechnicalMessages
    let serverVersion, dialectVersion, requestID: String
    
    enum CodingKeys: String, CodingKey {
        case stopLocationOrCoordLocation
        case technicalMessages = "TechnicalMessages"
        case serverVersion, dialectVersion
        case requestID = "requestId"
    }
}

// MARK: - StopLocationOrCoordLocation
struct StopLocationOrCoordLocation: Codable {
    let stopLocation: StopLocation
    
    enum CodingKeys: String, CodingKey {
        case stopLocation = "StopLocation"
    }
}

// MARK: - StopLocation
struct StopLocation: Identifiable, Codable {
    let locationNotes: LocationNotes
    let altID: [String]
    let timezoneOffset: Int
    let id, extID, name: String
    let lon, lat: Double
    let weight, products: Int
    
    enum CodingKeys: String, CodingKey {
        case locationNotes = "LocationNotes"
        case altID = "altId"
        case timezoneOffset, id
        case extID = "extId"
        case name, lon, lat, weight, products
    }
}

// MARK: - LocationNotes
struct LocationNotes: Codable {
    let locationNote: [LocationNote]
    
    enum CodingKeys: String, CodingKey {
        case locationNote = "LocationNote"
    }
}

// MARK: - LocationNote
struct LocationNote: Codable {
    let value, key, type, txtN: String
}

// MARK: - TechnicalMessages
struct TechnicalMessages: Codable {
    let technicalMessage: [TechnicalMessage]
    
    enum CodingKeys: String, CodingKey {
        case technicalMessage = "TechnicalMessage"
    }
}

// MARK: - TechnicalMessage
struct TechnicalMessage: Codable {
    let value, key: String
}

相关问题