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

Swift中如何处理值类型动态变化的JSON解码?

适配多类型data字段的Swift Codable实现

针对后端返回的data字段存在三种类型的情况,我们可以通过自定义遵循Decodable协议的枚举来处理,无需修改后端逻辑。

步骤1:定义自定义枚举处理多类型解码

创建枚举RegistrationData,枚举成员对应三种返回情况,并在init(from:)方法中依次尝试解码不同类型:

enum RegistrationData: Decodable {
    case success(Bool)
    case singleError(String)
    case multipleErrors([String])
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        // 优先尝试解码布尔值(注册成功场景)
        if let successFlag = try? container.decode(Bool.self) {
            self = .success(successFlag)
            return
        }
        
        // 尝试解码单个字符串(单条错误原因场景)
        if let singleErr = try? container.decode(String.self) {
            self = .singleError(singleErr)
            return
        }
        
        // 最后尝试解码字符串数组(多条错误原因场景)
        if let multiErrs = try? container.decode([String].self) {
            self = .multipleErrors(multiErrs)
            return
        }
        
        // 所有类型都不匹配时抛出解码错误
        throw DecodingError.dataCorruptedError(
            in: container,
            debugDescription: "无法识别的data字段类型"
        )
    }
}

步骤2:定义注册响应结构体

创建包含后端返回字段的结构体,其中data字段使用上面定义的RegistrationData类型:

struct RegistrationResponse: Decodable {
    let code: Int          // 后端状态码,比如200=成功,400=失败
    let message: String?   // 可选的全局提示信息
    let data: RegistrationData
}

步骤3:解码与结果处理

通过JSONDecoder解码响应数据后,使用switch语句处理不同的返回情况:

// 示例:解码不同场景的JSON响应
func handleRegistrationResponse(jsonStr: String) {
    guard let jsonData = jsonStr.data(using: .utf8) else {
        print("无效的JSON字符串")
        return
    }
    
    do {
        let response = try JSONDecoder().decode(RegistrationResponse.self, from: jsonData)
        switch response.data {
        case .success(let isSuccess):
            print("注册成功:\(isSuccess)")
        case .singleError(let errMsg):
            print("注册失败:\(errMsg)")
        case .multipleErrors(let errList):
            print("注册失败,原因:\(errList.joined(separator: ";"))")
        }
    } catch {
        print("解码失败:\(error.localizedDescription)")
    }
}

// 测试不同场景
let successJson = """
{"code":200,"message":"注册成功","data":true}
"""
handleRegistrationResponse(jsonStr: successJson)

let singleErrJson = """
{"code":400,"message":"注册失败","data":"用户名已存在"}
"""
handleRegistrationResponse(jsonStr: singleErrJson)

let multiErrJson = """
{"code":400,"message":"注册失败","data":["用户名已存在","密码长度不足6位"]}
"""
handleRegistrationResponse(jsonStr: multiErrJson)

补充说明

  • 如果需要将数据编码回JSON(比如调试时),可以让RegistrationData遵循Codable并实现encode(to:)方法:
    extension RegistrationData: Encodable {
        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            switch self {
            case .success(let flag): try container.encode(flag)
            case .singleError(let msg): try container.encode(msg)
            case .multipleErrors(let list): try container.encode(list)
            }
        }
    }
    
  • 解码顺序可以根据后端返回的优先级调整,确保最常见的场景优先尝试,提升解码效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:52:40