SwiftUI中typeMismatch错误求助:代码修正方案
解决JSON解码中
totalBooks等字段的类型不匹配问题 问题重现
运行代码时触发类型不匹配错误:
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "userslist", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "totalBooks", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))
已处理id字段的数字/字符串兼容,但totalBooks、totalBookViews等字段存在同样问题——API返回数字类型,模型却定义为String类型。
修正方案
核心逻辑是给需要兼容数字/字符串的字段添加通用解码工具,避免重复编写try-catch逻辑,同时修复潜在的崩溃风险。
1. 新增通用解码扩展
在代码中添加KeyedDecodingContainer的扩展,封装兼容数字转字符串的解码逻辑:
extension KeyedDecodingContainer { // 处理必填字段:数字/字符串转String func decodeStringOrInt(forKey key: Key) throws -> String { do { return try decode(String.self, forKey: key) } catch DecodingError.typeMismatch { let intValue = try decode(Int.self, forKey: key) return String(intValue) } } // 处理可选字段:数字/字符串转String? func decodeOptionalStringOrInt(forKey key: Key) throws -> String? { guard contains(key) else { return nil } if let strValue = try? decodeIfPresent(String.self, forKey: key) { return strValue } else if let intValue = try? decodeIfPresent(Int.self, forKey: key) { return String(intValue) } return nil } }
2. 修改UserslistModel的解码实现
替换原有的init(from decoder:)方法,使用工具方法处理兼容字段:
// MARK: - UserslistModel public struct UserslistModel: Decodable, Hashable { public var id: String public var full_name: String public var totalBookViews: String public var totalBooks: String? public var full_address: String? private enum CodingKeys: String, CodingKey { case id, full_name, totalBookViews, totalBooks, full_address } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 固定字符串字段直接解码 full_name = try container.decode(String.self, forKey: .full_name) full_address = try container.decodeIfPresent(String.self, forKey: .full_address) // 用工具方法处理兼容字段 id = try container.decodeStringOrInt(forKey: .id) totalBookViews = try container.decodeStringOrInt(forKey: .totalBookViews) totalBooks = try container.decodeOptionalStringOrInt(forKey: .totalBooks) } }
3. 修复View中的强制解包风险
原代码中Text(item.totalBooks!)使用强制解包,若API返回totalBooks为nil会直接崩溃,替换为默认值:
struct PublisherDataView: View{ @StateObject var list = PublisherModelVM() @State var logourl: String? var body: some View{ ScrollView(.horizontal,showsIndicators: false){ HStack{ ForEach( list.datas, id: \.id){ item in VStack(spacing: 12){ Text(item.full_name ) Text(item.full_address ?? "-") Text(item.totalBookViews) // 替换强制解包为默认值 Text(item.totalBooks ?? "-") } .frame(width:275, height: 220) .background(Color.brown.opacity(0.5)).cornerRadius(12) } } } } }
额外说明
- 通用解码工具可复用在所有需要兼容数字/字符串的字段上,减少冗余代码
- 改用
decodeIfPresent处理可选字段,避免API返回null时解码失败 - 移除View中的强制解包,提升代码稳定性
内容的提问来源于stack exchange,提问作者Anup Kumar Mishra
相关产品推荐
相关产品推荐

