0

I use code that downloads and displays json data from a number of different public json sites such as Apple Music and jsonplaceholder. I have some test data in a bin at jsonbin.io. When I use the same code I cannot get the data to populate a list in SwiftUI. The test data is a public json and is non-sensitive. Any idea what I am doing wrong?

struct Facility: Codable, Identifiable {
var id: String
var facilityName: String
}


struct FacilityView: View {


@State private var facilities = [Facility]()

var body: some View {
    NavigationView {
    List(facilities, id: \.id) {item in
        VStack {
            Text(item.id)
                .font(.headline)
            Text(item.facilityName)
            }
        }
    .navigationTitle("Facilities")
    
    .task {
        await fetchData()
    }
}
}

func fetchData() async {
    guard let url = URL(string: "https://api.jsonbin.io/v3/b/66130dbead19ca34f85689bc") else {
        print("URL does not work")
        return
        }
    do {
        let (data, _) = try await URLSession.shared.data( from: url)

        if let decodedResponse = try? JSONDecoder().decode([Facility].self, from: data) {
            facilities = decodedResponse
        }
    } catch {
        print("Data not valid")
    }
}
}

#Preview {
FacilityView()
}
1
  • Thank you very much. That appears to work on my sample data. I'll now try on the full real data set. Commented May 9, 2024 at 17:26

1 Answer 1

0

The response you get from the server is not an array [Facility]. So trying to decode this gives you an error that you should print, as shown in the example code.

Try this approach using a set of models that match the json data.

Note, don't use try? and print the actual error print("Data not valid \(error)")

struct ServerResponse: Codable {
    let record: [Facility]
    let metadata: Metadata
}

struct Metadata: Codable {
    let id: String
    let metaPrivate: Bool
    let createdAt: String

    enum CodingKeys: String, CodingKey {
        case id
        case metaPrivate = "private"
        case createdAt
    }
}

struct Facility: Codable, Identifiable {
    var id: String
    var facilityName: String
}

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

struct FacilityView: View {
    @State private var facilities = [Facility]()
    
    var body: some View {
        NavigationView {
            List(facilities) { item in
                VStack {
                    Text(item.id).font(.headline)
                    Text(item.facilityName)
                }
            }
            .navigationTitle("Facilities")
            .task {
                await fetchData()
            }
        }
    }
    
    func fetchData() async {
        guard let url = URL(string: "https://api.jsonbin.io/v3/b/66130dbead19ca34f85689bc") else {
            print("URL does not work")
            return
        }
        do {
            let (data, _) = try await URLSession.shared.data( from: url)
            let decodedResponse = try JSONDecoder().decode(ServerResponse.self, from: data)
            facilities = decodedResponse.record
        } catch {
            print("Data not valid \(error)") // <--- important
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.