json 如何在SwiftUI中将dat设置为二维阵列类型Api的视图?

sqserrrh  于 2022-11-19  发布在  Swift
关注(0)|答案(1)|浏览(72)

我在Json文件中有2D类型的数组数据,并希望在视图模型中提取数据,我尝试了很多次,但无法提取数据。我使用了从QuickType.io生成的模型。我使用MVVM模式提取数据。
这是我Json数据

{ "publisherPlans": [[ "Name", "Free","Prime" ],["Book Sell",9999,9999],["Book Bulk Sell",0,9999],["Magazine start-up",9999,9999],["Demo book request count for School",5,9999],["Demo book request Acception",9999,9999],["Assign book for demo",25,9999]]}

这是我模型,由网站生成

public struct SchoolPlanModel: Decodable {
    public let publisherPlans: [[PublisherPlan]]

}

public enum PublisherPlan:Decodable {
    case integer(Int)
    case string(String)
}

这是我的ViewModel,我正在尝试从Json文件中获取数据

class ReadData: ObservableObject {
    @Published var datas = [String]()
    
    func getData() async {
        guard let url = URL(string: "********api/plans") else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            Task{@MainActor in
                let results = try JSONDecoder().decode(SchoolPlanModel.self, from: data).publisherPlans
  print(results)
            }
        } catch {
            print("---> error: \(error)")
        }
    }
}

这是我的视图我想在这里显示数据。

struct SchoolPlanView: View{
    @StateObject var list = ReadData()
    
    var body: some View{
        ForEach(list.datas,id: \.self) { array in
                HStack{
                    ForEach(array.utf8CString, id: \.self) { element in
                        Text("\(element)")
                  }
                }
              }
        
    }
}
0lvr5msh

0lvr5msh1#

试试这个方法,对我很有效。2我不得不在你的代码中修改一些东西,但是应该很容易理解。3如果你需要更多的解释,请告诉我。

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

struct SchoolPlanModel: Decodable {
    var publisherPlans: [[PublisherPlan]]
}

enum PublisherPlan: Decodable, Hashable {
    case integer(Int)
    case string(String)

    // -- here 
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(Int.self) {
            self = .integer(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        throw DecodingError.typeMismatch(PublisherPlan.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Plan"))
    }
}

class ReadData: ObservableObject {
    @Published var datas: [[PublisherPlan]] = []  // <-- here
    
    func getData() async {
        guard let url = URL(string: "https://www.alibrary.in/api/plans") else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            Task{@MainActor in
                let results = try JSONDecoder().decode(SchoolPlanModel.self, from: data)
                self.datas = results.publisherPlans // <-- here
            }
        } catch {
            print("---> error: \(error)")
        }
    }
}

struct SchoolPlanView: View{
    @StateObject var list = ReadData()
    
    var body: some View {
        // -- here
        List(list.datas, id: \.self) { array in
            HStack{
                ForEach(array, id: \.self) { item in
                    switch item {
                       case .integer(let int): Text("\(int)")
                       case .string(let str): Text(str)
                    }
                }
            }
        }
        .task {
            await list.getData()  // <-- here
        }
    }
}

编辑-1:
要获取列标题,请尝试此方法,在getData()中,在源位置将数据和标题分开。您必须使用列等调整显示...

class ReadData: ObservableObject {
    @Published var datas: [[PublisherPlan]] = []
    @Published var headings: [String] = []  // <-- here
    
    func getData() async {
        guard let url = URL(string: "https://www.alibrary.in/api/plans") else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            //       print("\n \(String(data: data, encoding: .utf8) as AnyObject) \n")
            Task{@MainActor in
                let results = try JSONDecoder().decode(SchoolPlanModel.self, from: data)
                // the data minus the first array of headings
                datas = Array(results.publisherPlans.dropFirst()) // <-- here
                // get the headings
                if let headers = results.publisherPlans.first { // <-- here
                    for h in headers {
                        switch h {
                           case .integer(_): break
                           case .string(let str): self.headings.append(str)
                        }
                    }
                }
            }
        } catch {
            print("---> error: \(error)")
        }
    }
}

struct SchoolPlanView: View{
    @StateObject var list = ReadData()
    
    var body: some View {
        VStack {
            HStack {
                ForEach(list.headings, id: \.self) { heading in  // <-- here
                    Text(heading)
                }
            }
            List(list.datas, id: \.self) { array in
                HStack {
                    ForEach(array, id: \.self) { item in
                        switch item {
                        case .integer(let int): Text("\(int)")
                        case .string(let str): Text(str)
                        }
                    }
                }
            }
        }
        .task {
            await list.getData()
        }
    }
}

相关问题