skip to Main Content
{
"data":{
"email":"[email protected]", 
"password":"123",
"token":""
} 
}



struct JsonResult: View{
    @State private var results = [GetData]()
    var body: some View{
        List(results, id: .email){ item in
            VStack(alignment: .leading) {
                Text(item.password)
                    .font(.headline)
                Text(item.token)
                    .font(.headline)
            }
            
        }.task {
            await loadData()
        }
    }

struct Response : Codable {
        var results: [GetData]
    }
    
    struct GetData: Codable{
        var data : [Result]
    }
    
    struct Result: Codable {
        var email: String
        var password: String
        var token: String
    }
    func loadData() async{
        guard let url = URL(string: "MYURL") else {
            print("invalid URL")
            return
        }
        do{
            let(data,_) = try await URLSession.shared.data(from: url)
            // more code
            if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data)
            {
                results = decodedResponse.results
            }
        } catch {
            print("Invalid Data")
        }
    }

}

i need to know if the codable structure is right according to the structure of data i gave ? and also the fetching in list ? please i need help in the URLsession i am still new and i barely know about url alot !

i would be grateful if you help me ! thank you verrrry much !!!!

2

Answers


  1. struct Response : Decodable, Hashable {
        var results: [GetData]
    }
    
    struct GetData: Decodable, Hashable{
        var data : [Result]
    }
    
    struct Result: Decodable, Hashable {
        var email: String
        var password: String
        var token: String
    }
    
    enum RequestError: Error {
        case invalidURL
        case missingData
    }
    
    class JsonResultViewModel: ObservableObject{
        
        @Published var response = [Response]()
        
        func performHTTPRequest(urlString: String) async throws{
            guard let url = URL(string: urlString) else {throw RequestError.invalidURL}
            guard let (data, resp) = try? await URLSession.shared.data(from: url) else{throw RequestError.invalidURL}
            guard (resp as? HTTPURLResponse)?.statusCode == 200 else {throw RequestError.invalidURL}
            let decoder = JSONDecoder()
            guard let jsonResponse = try? decoder.decode([Response].self, from: data) else {throw RequestError.missingData}
            DispatchQueue.main.async {
               self.response = jsonResponse 
            }
        }
    }
    
    
    
    struct ContentView: View {
        @StateObject private var results = JsonResultViewModel()
        var body: some View {
            List(results.response.indices, id: .self){ index in
                VStack(alignment: .leading) {
                    Text(results.response[index].results[index].data[index].email)
                        .font(.headline)
                    Text(results.response[index].results[index].data[index].token)
                        .font(.headline)
                }
            }
            .onAppear(perform: {
                Task{
                    do {
                        try await results.performHTTPRequest(urlString: "wwww.url.com")
                    } catch RequestError.invalidURL{
                        print("invalid URL")
                    } catch RequestError.missingData{
                        print("missing data")
                    }
                }
            })
            
        }
    }
    
    Login or Signup to reply.
  2. In the JSON there is no array involved (no [] at all).

    The model corresponding to the JSON is

    struct Response: Decodable {
        let data : UserData
    }
    
    struct UserData: Decodable {
        let email: String
        let password: String
        let token: String
    }
    

    So the data source cannot be declared as an array. To avoid an optional type create an enum with associated values indicating a state. The benefit is that you can show different views depending on the state

    struct JsonResult: View {
    
        enum LoadingState {
            case idle, loading, loaded(UserData), failure(Error)
        }
    

    this is the rest of the struct, consider that there is no List either because UserData is a single object.

        @State private var state : LoadingState = .idle
        
        var body: some View {
            VStack {
                switch state {
                    case .idle: EmptyView()
                    case .loading: ProgressView()
                    case .loaded(let userData):
                        
                        VStack(alignment: .leading) {
                            Text(userData.password)
                                .font(.headline)
                            Text(userData.email)
                                .font(.headline)
                        }
                        
                    case .failure(let error): Text(error.localizedDescription)
                }
            }.task {
                await loadData()
            }
        }
        
        func loadData() async {
            
            state = .loading
            guard let url = URL(string: "MYURL") else {
                state = .failure(URLError(.badURL))
                return
            }
            do {
                let (data,_) = try await URLSession.shared.data(from: url)
                // more code
                let decodedResponse = try JSONDecoder().decode(Response.self, from: data)
                state = .loaded(decodedResponse.data)
                
            } catch {
                state = .failure(error)
                print(error) // this shows the real DecodingError
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search