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
相关产品推荐
相关产品推荐

