Ожидается декодировать Int, но найдена строка - PullRequest
0 голосов
/ 11 сентября 2018

Мой JSON выглядит так:

{
    "status": true,
    "data": {
        "img_url": "/images/houses/",
        "houses": [
            {
                "id": "1",
                "name": "Kapital",
                "url": "https://kapital.com/",
                "img": "10fbf4bf6fd2928affb180.svg"
            }
        ]
     }
 }

И я использую следующие структуры:

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
}

Но когда я использую:

let houses = try JSONDecoder().decode(ServerStatus.self, from: data)

Я получаю следующую ошибку:

3 : CodingKeys(stringValue: "id", intValue: nil)
  - debugDescription : "Expected to decode Int but found a string/data instead."

Я впервые использую Decodables, и я погуглил эту проблему, но не смог ее исправить. Может ли кто-нибудь помочь мне выяснить, в чем дело, и, возможно, объяснить мне это?

Когда я удаляю data часть из ServerStatus, все работает. Так что проблема в разборе data part

1 Ответ

0 голосов
/ 11 сентября 2018

Измените House структуру на это:

House: Decodable {
    let id: String
    let name: String
    let url: String
    let img: String
}

id должно быть String. И чтобы получить дома:

let houses = try JSONDecoder().decode(ServerStatus.self, from: data).data.houses

Если вы не хотите изменять id, поступающий с сервера, на Int, вы можете предоставить собственную реализацию Encodable и Decodable, чтобы определить собственную логику кодирования и декодирования.

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)
...