You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift的Decodable类如何为属性设置解码别名匹配API返回的JSON字段

解决方案

该需求完全可以实现,Swift 原生 Decodable 协议已内置支持 JSON 字段和自定义属性名的映射能力,无需引入第三方依赖。

原生标准实现(推荐)

通过定义 CodingKeys 枚举指定映射关系,等效于 Kotlin 中的 @SerializedName 注解,写法简洁且兼容性最好:

class Client: Identifiable, Decodable {
    let id: Int
    let token: String

    // 枚举值对应类的属性,rawValue对应JSON返回的字段名
    enum CodingKeys: String, CodingKey {
        case id = "cliente_id" // 将JSON的cliente_id字段映射到id属性
        case token // 字段名和属性名一致时无需指定别名
    }

    init(id: Int, token: String) {
        self.id = id
        self.token = token
    }
}

你原有基于 Alamofire 的请求代码不需要做任何修改,解码时会自动完成字段匹配。

兼容多别名的实现

如果需要和 Kotlin 中 @SerializedName 的 alternate 参数一样,同时兼容多个JSON字段名映射到同一个属性,可以手动实现解码初始化方法:

class Client: Identifiable, Decodable {
    let id: Int
    let token: String

    enum CodingKeys: String, CodingKey {
        case token
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        token = try container.decode(String.self, forKey: .token)

        // 兼容cliente_id和id两个JSON字段
        let dynamicContainer = try decoder.container(keyedBy: GenericCodingKey.self)
        if let clientId = try dynamicContainer.decodeIfPresent(Int.self, forKey: GenericCodingKey(stringValue: "cliente_id")) {
            id = clientId
        } else if let fallbackId = try dynamicContainer.decodeIfPresent(Int.self, forKey: GenericCodingKey(stringValue: "id")) {
            id = fallbackId
        } else {
            throw DecodingError.keyNotFound(
                GenericCodingKey(stringValue: "id"),
                .init(codingPath: decoder.codingPath, debugDescription: "未找到有效的id字段")
            )
        }
    }

    init(id: Int, token: String) {
        self.id = id
        self.token = token
    }
}

// 通用动态CodingKey实现,用于匹配任意字段名
fileprivate struct GenericCodingKey: CodingKey {
    var stringValue: String
    init(stringValue: String) {
        self.stringValue = stringValue
    }
    var intValue: Int?
    init?(intValue: Int) { nil }
}

自定义注解式实现

如果希望使用类似示例中 @NameforDecode 的注解写法,可以通过 Swift 属性包装器自定义实现,不过除非有特殊业务需求,否则更推荐使用原生的 CodingKeys 方案。


内容的提问来源于stack exchange,提问作者Sebastián García Burgos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:12:00