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

Swift中如何正确解析包含不同结构Responsible字段的复杂JSON数据

解决方案

思路判断

你提到的在初始化器中匹配类型赋值的思路是正确的,不过现有代码存在一个核心问题:Any类型不兼容Codable协议,无法直接参与编解码,需要先定义枚举类型承载两种不同的responsible结构。

类型定义修正

首先定义带关联值的枚举表示两种可能的负责人类型:

enum Responsible: Codable {
    case user(User)
    case userCategory(UserCategory)
    
    // 兜底解码逻辑:如果无法依赖type字段匹配,可以用该逻辑自动尝试两种类型
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        // 先尝试解码为User类型
        if let user = try? container.decode(User.self) {
            self = .user(user)
            return
        }
        // 尝试解码为UserCategory类型
        if let category = try? container.decode(UserCategory.self) {
            self = .userCategory(category)
            return
        }
        // 都匹配失败抛出解码错误
        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Responsible字段无法匹配已知类型"))
    }
}

然后修改MyJson的responsible类型,同时补充CodingKeys处理下划线命名到驼峰命名的映射,优先推荐结合返回的type字段做精准解码:

struct MyJson: Codable {
    let id: Int
    let createdAt: String
    let updatedAt: String
    let link: String
    let type: String
    let responsible: Responsible
    
    enum CodingKeys: String, CodingKey {
        case id, link, type, responsible
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }
    
    // 结合type字段的精准解码逻辑,效率更高,避免结构重叠导致的误判
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 解码通用字段
        id = try container.decode(Int.self, forKey: .id)
        createdAt = try container.decode(String.self, forKey: .createdAt)
        updatedAt = try container.decode(String.self, forKey: .updatedAt)
        link = try container.decode(String.self, forKey: .link)
        type = try container.decode(String.self, forKey: .type)
        
        // 根据type字段匹配对应的responsible类型
        switch type {
        case "u":
            let user = try container.decode(User.self, forKey: .responsible)
            responsible = .user(user)
        case "r":
            let category = try container.decode(UserCategory.self, forKey: .responsible)
            responsible = .userCategory(category)
        default:
            throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "未知的type类型: \(type)")
        }
    }
}

// 子模型补充CodingKeys处理下划线字段,注意comment可能返回null需要定义为可选类型
struct User: Codable {
    let id: Int
    let type, email, phone, comment: String?
    let firstName, secondName: String
    
    enum CodingKeys: String, CodingKey {
        case id, type, email, phone, comment
        case firstName = "first_name"
        case secondName = "second_name"
    }
}

struct UserCategory: Codable {
    let id: Int
    let name, guardName, createdAt, updatedAt: String
    
    enum CodingKeys: String, CodingKey {
        case id, name
        case guardName = "guard_name"
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }
}

解码使用示例

直接用JSONDecoder解码整个数组即可:

let decoder = JSONDecoder()
do {
    let result = try decoder.decode([MyJson].self, from: jsonData)
    // 遍历使用responsible字段
    for item in result {
        switch item.responsible {
        case .user(let user):
            print("用户类型负责人:\(user.firstName ?? "")")
        case .userCategory(let category):
            print("分类类型负责人:\(category.name)")
        }
    }
} catch {
    print("解码失败:\(error)")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 00:18:02