Reputation: 57
{
"records": [
{
"id": 1,
"customers_name": "Acme 1"
},
{
"id": 2,
"customers_name": "Acme2"
}
]
}
This is my really simple JSON scheme, but I can't get JSONDecoder() to work. My error code is:
Expected to decode Array but found a dictionary instead.
Here are my two files that I'm currently using:
Customer.swift
struct Customer: Decodable, Identifiable {
public var id: String
public var customers_name: String
enum CodingKeys: String, CodingKey {
case id = "id"
case customers_name = "customers_name"
}
init(from decoder: Decoder) throws{
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
customers_name = (try container.decodeIfPresent(String.self, forKey: .customers_name)) ?? "Unknown customer name"
}
}
CustomerFetcher.swift
import Foundation
public class CustomerFetcher: ObservableObject {
@Published var customers = [Customer]()
init(){
load()
}
func load() {
let url = URL(string: "https://somedomain.com/customers.json")!
URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
print(d)
let decodedLists = try JSONDecoder().decode([Customer].self, from: d)
DispatchQueue.main.async {
self.customers = decodedLists
}
} else {
print("No Data")
}
} catch {
print (error)
}
}.resume()
}
}
I believe it's because of this nested JSON structure and tried so many things, but still can't get it working.
Thank you so much, if anyone would help me out!
Upvotes: 0
Views: 188
Reputation: 130200
You are forgetting the wrapping object:
struct RecordList<T: Decodable>: Decodable {
let records: [T]
}
let decodedLists = try JSONDecoder().decode(RecordList<Customer>.self, from: d)
DispatchQueue.main.async {
self.customers = decodedLists.records
}
Also note the Customer
can be reduced to:
struct Customer: Decodable, Identifiable {
public var id: String
public var customersName: String
enum CodingKeys: String, CodingKey {
case id
case customersName = "customers_name"
}
}
You can also setup your JSONDecoder
to convert underscores to camel case automatically. Then you won't even need the CodingKeys
.
Upvotes: 2