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

Swift中如何使用CodingKeys解析动态JSON键?

Swift Codable 解析动态键对应字段的实现方案

要处理JSON中动态变化的键对应permissions字段的解析,不能依赖自动合成的Codable实现,需要自定义解码逻辑,具体步骤如下:

1. 定义辅助的动态CodingKey

首先创建一个可以适配任意字符串键的CodingKey类型:

struct DynamicCodingKey: CodingKey {
    let stringValue: String
    init?(stringValue: String) {
        self.stringValue = stringValue
    }

    var intValue: Int?
    init?(intValue: Int) {
        return nil
    }
}

2. 修改Functionality结构体,自定义解码逻辑

将固定字段和动态字段的解析分开处理:

struct Functionality: Codable {
    let subCod: String?
    let parentFunctionality: String?
    let transaccional: String?
    let permissions: MyModel?

    // 仅用于固定字段的CodingKey
    private enum FixedCodingKeys: String, CodingKey {
        case subCod, parentFunctionality, transaccional
    }

    init(from decoder: Decoder) throws {
        // 1. 解析固定字段
        let fixedContainer = try decoder.container(keyedBy: FixedCodingKeys.self)
        subCod = try fixedContainer.decodeIfPresent(String.self, forKey: .subCod)
        parentFunctionality = try fixedContainer.decodeIfPresent(String.self, forKey: .parentFunctionality)
        transaccional = try fixedContainer.decodeIfPresent(String.self, forKey: .transaccional)

        // 2. 处理动态键的permissions字段
        let allContainer = try decoder.container(keyedBy: DynamicCodingKey.self)
        var tempPermissions: MyModel?

        // 遍历所有键,排除固定字段后尝试解码为MyModel
        for key in allContainer.allKeys {
            // 跳过固定字段的键
            guard !FixedCodingKeys.allCases.contains(where: { $0.rawValue == key.stringValue }) else {
                continue
            }
            // 解码该键对应的值为MyModel
            tempPermissions = try allContainer.decodeIfPresent(MyModel.self, forKey: key)
            break // 假设仅存在一个动态键对应permissions,找到即退出
        }

        permissions = tempPermissions
    }
}

3. 针对动态键的规则调整(可选)

如果你的动态键有特定规则(比如包含特定字符串、固定前缀等),可以修改遍历逻辑,精准匹配目标键:

// 替换遍历部分的代码,示例:匹配包含"permission"的键
for key in allContainer.allKeys {
    if key.stringValue.lowercased().contains("permission") {
        tempPermissions = try allContainer.decodeIfPresent(MyModel.self, forKey: key)
        break
    }
}

编码支持(可选)

如果需要将结构体编码回JSON,需要自定义encode(to:)方法,注意要存储动态键的名称(可以给结构体添加额外属性permissionsKey: String来记录):

// 修改结构体,添加动态键存储属性
struct Functionality: Codable {
    let subCod: String?
    let parentFunctionality: String?
    let transaccional: String?
    let permissions: MyModel?
    let permissionsKey: String // 存储动态键的名称,编码时使用

    // ... 省略之前的FixedCodingKeys和init(from:) ...

    func encode(to encoder: Encoder) throws {
        // 编码固定字段
        var fixedContainer = encoder.container(keyedBy: FixedCodingKeys.self)
        try fixedContainer.encodeIfPresent(subCod, forKey: .subCod)
        try fixedContainer.encodeIfPresent(parentFunctionality, forKey: .parentFunctionality)
        try fixedContainer.encodeIfPresent(transaccional, forKey: .transaccional)

        // 编码动态键的permissions
        guard let permissions = permissions else { return }
        var dynamicContainer = encoder.container(keyedBy: DynamicCodingKey.self)
        guard let key = DynamicCodingKey(stringValue: permissionsKey) else { return }
        try dynamicContainer.encode(permissions, forKey: key)
    }
}

内容的提问来源于stack exchange,提问作者DanielColman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:50:25