json - 期望解码 Int 但发现了一个字符串

标签 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,我正在谷歌搜索这个问题,但无法解决。有人可以帮我找出问题所在并向我解释一下吗?

当我从 ServerStatus 中删除 data 部分时,一切正常。所以问题出在解析data部分

最佳答案

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

关于json - 期望解码 Int 但发现了一个字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52265674/

相关文章:

python - aesEncrypt 产生不同的结果

swift - 使用 Decodable 进行 JSON 解析时,optional 和 decodeIfPresent 有什么区别?

ios - 在 Swift 4 中解码泛型类的可编码树

swift - 将 Swift 结构定义移动到不同的文件会导致构建失败

java - 如何使用 Jackson 将对象附加到现有 JSON 文件

javascript - 将 JSON 存储在磁盘上不好吗?

javascript - 如何将表单字段的值设置为 JSON 中的值?

java - Jackson将json数组反序列化为一个类的单个属性

ios - swift : textFieldShouldBeginEditing function fix

ios - 用 UIBezierPath 画一条线