i am trying to create a CRM app, for this i created a database on my raspberry Pi, and used PHP to create JSON results on a url.
Now i have created the following Network manager in swift, but the invalidData error at the end in the catch keeps getting thrown. What am i doing wrong ?
import Foundation
final class NetworkManager {
static let shared = NetworkManager()
static let baseURL = ""
private let buyersURL = baseURL + ""
private init(){}
func getBuyers(completed: @escaping (Result<[Buyer], CRMError>) -> Void) {
guard let url = URL(string: buyersURL) else {
completed(.failure(.invalidURL))
return
}
let task = URLSession.shared.dataTask(with: URLRequest(url: url)) { data, response, error in
if let _ = error {
completed(.failure(.unableToComplete))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}
guard let data = data else {
completed(.failure(.invalidData))
return
}
do {
let decoder = JSONDecoder()
let decodedResponse = try decoder.decode(BuyerResponse.self, from: data)
completed(.success(decodedResponse.request))
} catch {
completed(.failure(.invalidData))
}
}
task.resume()
}
}
The following is the result of the JSON on the URL
and the following is my Buyer struct:
import Foundation
struct Buyer: Codable, Identifiable, Hashable{
let id: Int
let user_id: Int
let name: String
let email: String
let country: String
let phone: String
let second_phone: String
let whishes: String
let budget: String
let timing: String
let fase: String
let media: String
let plans: String
let extra: String
let hot: Int
}
struct BuyerResponse : Codable {
let request: [Buyer]
}
And this is the view in which i call get the buyers:
struct BuyersView: View {
@StateObject var viewModel = BuyersViewModel()
@State var path = NavigationPath()
@State private var buyers: [Buyer] = []
var body: some View {
NavigationStack(path: $path) {
VStack{
CategoryView(categories: viewModel.fases, currentSelection: $viewModel.currentFase)
HStack{
Spacer()
NavigationLink("Add buyer", value: 0)
.padding()
}
List(buyers){ buyer in
BuyerCellView(buyer: buyer)
}
}
// .navigationDestination(for: Int.self) { _ in
// AddBuyerView(path: $path, fases: viewModel.fases, medias: $viewModel.media)
// }.navigationDestination(for: Buyer.self) { buyer in
// BuyerDetailView(buyer: buyer)
// }
}.onAppear{
getBuyers()
}
}
func getBuyers() {
NetworkManager.shared.getBuyers { result in
DispatchQueue.main.async {
switch result {
case .success(let buyers):
self.buyers = buyers
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
}
I checked that the variables on the JSON and the struct of Buyer are the same, but the error keeps happening, i just expect that the variable buyers returns a list of Buyers from the JSON.
I folowed the tutorial of https://www.youtube.com/watch?v=b1oC7sLIgpI&t=22362s at around 6 hours into the video
Thank you for helping in advance

The inside of
BuyerResponseyou say that the JSON should look like this:But judging from your screenshot, the response looks like this:
Inside of your PHP script you should adjust the response so that you get that
request:before the list starts. That should do the trick.Another way would be to change that line here
to
That way you tell the decoder that it's getting a list of
Buyers without anything around it.Generally if you get an error at that position, it means that the data that you receive does not match the data structure that you specify.
A good way to approach this is to just create a model struct with only one property and check whether that works. Then add another property, etc. If it doesn't work: print the error you receive and that will tell you at what line of the JSON there is something unexpected.