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

Swift中JSON解码时如何处理UpdateNickname的Message空值问题

解决Swift中JSON解码时Message字段为null的报错问题

这个问题我做项目时也碰到过,核心原因很明确:你把UpdateNickname里的Message定义成了非可选的UpdateNicknameMessage类型,但当服务器返回null时,JSONDecoder无法将null映射到非可选值,直接抛出解码错误。下面给你两个最常用的修复方案,按需选择:

方案1:将Message字段改为可选类型(推荐)

这是最简单直接的方案,只需要把Message的类型从UpdateNicknameMessage改成UpdateNicknameMessage?,同时调整自定义初始化方法的逻辑:

struct UpdateNicknameMessage: Codable {
    let id: Int
    let nickname: String
    let email: String
}

struct UpdateNickname: Codable {
    var Status: Int
    var Result: String
    var Message: UpdateNicknameMessage? // 改为可选类型
    enum CodingKeys: String, CodingKey {
        case Status = "Status"
        case Result = "Result"
        case Message = "Message"
    }
    
    // 调整自定义初始化方法,允许Message为nil
    init?(from jsonObject: AnyObject) {
        guard let status1 = jsonObject.object(forKey: "Status") as? Int,
              let result1 = jsonObject.object(forKey: "Result") as? String else {
            return nil
        }
        Status = status1
        Result = result1
        // 不再强制校验Message,直接赋值(null时为nil)
        Message = jsonObject.object(forKey: "Message") as? UpdateNicknameMessage
    }
}

修改后,当服务器返回Message: null时,JSONDecoder会自动将Message设为nil,不会抛出解码错误。后续业务逻辑中可以通过可选绑定处理两种情况:

do {
    let model = try decoder.decode(UpdateNickname.self, from: data)
    if model.Status == 200 {
        if let message = model.Message {
            // 处理正常返回的Message数据
        }
    } else {
        // 服务器错误,此时Message大概率为nil
    }
} catch {
    print(error.localizedDescription)
}

方案2:给Message设置默认值(非可选场景)

如果你不想在业务代码中处理可选类型,希望Message始终有一个有效值,可以自定义解码逻辑,当字段为null时返回一个默认的UpdateNicknameMessage实例:

struct UpdateNickname: Codable {
    var Status: Int
    var Result: String
    var Message: UpdateNicknameMessage // 保持非可选
    enum CodingKeys: String, CodingKey {
        case Status = "Status"
        case Result = "Result"
        case Message = "Message"
    }
    
    // 自定义Codable解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        Status = try container.decode(Int.self, forKey: .Status)
        Result = try container.decode(String.self, forKey: .Result)
        // 尝试解码Message,失败(或为null)时使用默认值
        Message = try container.decodeIfPresent(UpdateNicknameMessage.self, forKey: .Message) ?? UpdateNicknameMessage(id: 0, nickname: "", email: "")
    }
    
    // 同步调整自定义初始化方法
    init?(from jsonObject: AnyObject) {
        guard let status1 = jsonObject.object(forKey: "Status") as? Int,
              let result1 = jsonObject.object(forKey: "Result") as? String else {
            return nil
        }
        Status = status1
        Result = result1
        
        if let messageDict = jsonObject.object(forKey: "Message") as? [String: Any] {
            // 尝试从字典解析Message,失败则用默认值
            guard let id = messageDict["id"] as? Int,
                  let nickname = messageDict["nickname"] as? String,
                  let email = messageDict["email"] as? String else {
                Message = UpdateNicknameMessage(id: 0, nickname: "", email: "")
                return
            }
            Message = UpdateNicknameMessage(id: id, nickname: nickname, email: email)
        } else {
            // Message为null时直接用默认值
            Message = UpdateNicknameMessage(id: 0, nickname: "", email: "")
        }
    }
}

这个方案的好处是业务代码不需要处理nil,但要注意默认值的合理性,避免后续逻辑出错。

额外建议:移除多余的自定义初始化方法

其实你的init?(from jsonObject: AnyObject)属于冗余代码——Codable协议已经为你提供了默认的JSON解码能力,如果不是必须要兼容AnyObject类型的输入,建议直接移除这个方法,只保留Codable的默认实现,这样代码会更简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:01:51