预期解码Int但找到一个字符串

时间:2018-09-10 21:24:11

标签: json swift decodable

我的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部分

1 个答案:

答案 0 :(得分:6)

将您的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)