My JSON looks like:
{
"status": true,
"data": {
"img_url": "/images/houses/",
"houses": [
{
"id": "1",
"name": "Kapital",
"url": "https://kapital.com/",
"img": "10fbf4bf6fd2928affb180.svg"
}
]
}
}
And I'm using the next structs:
struct ServerStatus: Decodable {
let status: Bool
let data: ServerData
}
struct ServerData: Decodable {
let img_url: String
let houses: [House]
}
struct House: Decodable {
let id: Int
let img: String
let name: String
let url: String
}
But when I'm using:
let houses = try JSONDecoder().decode(ServerStatus.self, from: data)
I get the next error:
3 : CodingKeys(stringValue: "id", intValue: nil)
- debugDescription : "Expected to decode Int but found a string/data instead."
It's my first time using Decodables and I'm googling this problem but was not able to fix it. Can someone help me to find out what's wrong and maybe explain me that?
When I remove data
part from the ServerStatus
everything works. So the problem is in parsing data
part
Change you House
struct to this:
House: Decodable {
let id: String
let name: String
let url: String
let img: String
}
id
should be a String
. And to get the houses:
let houses = try JSONDecoder().decode(ServerStatus.self, from: data).data.houses
If you don't want to change the id
coming from the server to Int
, you can provide a custom implementation of Encodable and Decodable to define your own encoding and decoding logic.
struct House {
let id: Int
let img: String
let name: String
let url: String
enum CodingKeys: String, CodingKey {
case id, img, name, url
}
}
extension House: Decodable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
guard let idInt = Int(try values.decode(String.self, forKey: .id)) else {
fatalError("The id is not an Int")
}
id = idInt
img = try values.decode(String.self, forKey: .img)
name = try values.decode(String.self, forKey: .name)
url = try values.decode(String.self, forKey: .url)
}
}
//Just in case you want to encode the House struct
extension House: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(String(id), forKey: .id)
try container.encode(img, forKey: .img)
try container.encode(name, forKey: .name)
try container.encode(url, forKey: .url)
}
}
let decoder = JSONDecoder()
let data = """
{
"status": true,
"data": {
"img_url": "/images/houses/",
"houses": [
{
"id": "1",
"name": "Kapital",
"url": "https://kapital.com/",
"img": "10fbf4bf6fd2928affb180.svg"
}
]
}
}
""".data(using: .utf8)!
let houses = try JSONDecoder().decode(ServerStatus.self, from: data).data.houses
print(houses)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With