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

Posted

技术标签:

【中文标题】预计解码 Int 但找到一个字符串【英文标题】:Expected to decode Int but found a string 【发布时间】:2019-02-15 08:29:05 【问题描述】:

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

【问题讨论】:

id 是 JSON 中的字符串,但您的 structid 定义为 Int。将其更改为String,问题就消失了。 @rmaddy 哇!那太快了!非常感谢!但是一个简单的问题,我怎样才能将ID 保存为整数? @J.Doe 你不能在服务器端发送一个 Int 吗? 看起来在未来,我们将能够选择加入 string-as-int 行为。见bugs.swift.org/browse/SR-5249。同时,转到该链接并支持该问题:)。 @ielyamani,你如何从服务器发送一个 int? json 编码时,所有数值都会自动用引号括起来。我不知道你将如何从服务器返回一个实际的整数。 【参考方案1】:

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)

【讨论】:

基于 cmets,OP 希望 id 成为 Int,所以现在的问题是如何将 JSON 中的字符串转换为结构中所需的 Int 值。

以上是关于预计解码 Int 但找到一个字符串的主要内容,如果未能解决你的问题,请参考以下文章

预计解码字典 但发现了一个字符串/数据

JSONDecoder - “预期解码 Dictionary<String, Any> 但找到了一个字符串/数据。”

Swift Codable 期望解码 Dictionary<String, Any> 但找到了一个字符串/数据

Php json将所有值解码为字符串

疑难解答“TypeError:ord() 预期的长度为 1 的字符串,但找到了 int”

IText7如何解码字段的默认外观int字体对象及其属性