Swift类型不符合“可解码”

c3frrgcw  于 2023-02-18  发布在  Swift
关注(0)|答案(2)|浏览(228)

我正在尝试编写一个UserModel类来帮助我对JSON响应进行解码,但遇到了以下错误:
Type 'UserModel' does not conform to protocol 'Decodable'
我的UserModel结构如下所示。

struct UserModel: Codable, Hashable, Identifiable {
    let id: String
    let email: String
    let tokenIssuedAt: Int
    let createdAt: String
    let updatedAt: String
    let settings: Settings

    enum CodingKeys: String, CodingKey {
        case tokenIssuedAt = "token_issued_at"
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }
    
    struct Settings: Codable {
        var wishlists, collection, findable: Bool
    }
}

如果我从这个结构体中删除设置变量以及设置结构体,这个错误就会消失,但是考虑到设置是可编码的,我很困惑为什么这会导致我的UserModel结构体中断。
我已尝试将编码密钥更新为以下内容:

enum CodingKeys: String, CodingKey {
    case id
    case email
    case tokenIssuedAt = "token_issued_at"
    case createdAt = "created_at"
    case updatedAt = "updated_at"
    case settings
}

以及增加初始化解码器,例如:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    settings = try container.decode(Settings.self, forKey: .settings)
}

但是,我收到以下错误消息:
类型“UserModel”不符合协议“Equatable”类型“UserModel”不符合协议“Hashable”
这是因为我在编码键、设置结构体中犯了错误,还是因为我在stub这个结构体时忽略了其他东西?
我尝试解码的JSON如下所示:

[
    {
        "id": "1cc02c5f-2cb3-4546-a2d7-a824188e667d",
        "email": "trenton@example.com",
        "token_issued_at": 1676418140,
        "created_at": "2023-02-09T01:51:08.733Z",
        "updated_at": "2023-02-14T23:46:14.136Z",
        "settings": {
            "collection": false,
            "wishlist": false,
            "findable": true
        }
]
jm81lzqq

jm81lzqq1#

尝试这种方法,

struct UserModel: Codable, Identifiable {  // <-- here
    
    let id: String
    let email: String
    let tokenIssuedAt: Int
    let createdAt: String
    let updatedAt: String
    let settings: Settings

    enum CodingKeys: String, CodingKey {
        case tokenIssuedAt = "token_issued_at"
        case createdAt = "created_at"
        case updatedAt = "updated_at"
        case id, email, settings   // <-- here
    }
    
    struct Settings: Codable {
        var wishlist, collection, findable: Bool  // <-- here wishlist, not s
    }
    }

注意,如果您确实需要UserModel中的Hashable,请将其也放在Settings

mwyxok5s

mwyxok5s2#

你的第一次尝试没有成功,因为你只在CodingKeys枚举中指定了你想解码的密钥的子集。对于编译器来说,这意味着你 * 只 * 想解码JSON中的那些密钥。但是,如果只解码那些密钥,那么idemailsettings在解码时将不会被初始化为任何值,这是违反Swift规则的。
当您将所有键添加到CodingKeys中时,仍然存在UserModel不符合HashableEquatable的错误。这是因为Settings不符合其中任何一个。为了自动生成Hashable的一致性,所有成员都需要是Hashable
要么使Settings符合Hashable

struct Settings: Hashable, Codable {
    var wishlist, collection, findable: Bool
}

或者使UserModel * 不 * 符合Hashable

struct UserModel: Codable, Identifiable {

将修复错误。
你应该删除你添加的init(from:),因为它 * 只 * 解码settings。你可以只使用Swift自动生成的一个。
实际上,您也可以删除UserModel中的编码键enum。从snake caseMap编码键可以通过解码器中的convertFromSnakeCase选项来完成。您可以在解码时在解码器中设置此选项:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

相关问题