Swift中如何访问含可选值的嵌套JSON数据?
解决带可选属性的嵌套JSON数据访问问题
问题概述
已定义包含可选属性的Codable结构体,能成功解码API返回的嵌套JSON数据并在控制台打印结果,但存在两个问题:
- 无法访问
Variation2结构体中的variation_saleprice值 - 尝试通过
try JSONDecoder().decode(CategoryViewModel2.self, from: ...).data.item链式访问时,Xcode无法识别item变量
问题原因分析
- 类型不匹配导致解码失败:API返回的JSON中,
variation_saleprice存在5.5这类浮点数值,但结构体Variation2中对应的variationSaleprice被定义为Int?类型,类型不匹配会导致该字段解码后为nil。 - 嵌套可选值的访问逻辑错误:
CategoryViewModel2的data是[Datum2]?(可选数组),数组类型无法直接访问item属性,必须先遍历数组或取出具体元素;同时Datum2的item又是[Item2]?(可选数组),层级嵌套的可选值不能直接链式访问。
修复步骤
1. 修正类型不匹配问题
将Variation2结构体中variationPrice、variationSaleprice以及对应JSON中带小数的the4字段的类型从Int?改为Double?,匹配JSON中的浮点数值:
// MARK: - Variation struct Variation2: Codable { let the0, the1: Int? let the2: String? let the3: Int? let the4: Double? // JSON中"4"对应值含小数,需改为Double let id, itemID: Int? let attributeValue: String? let variationPrice: Double? let variationSaleprice: Double? let isCart: Int? enum CodingKeys: String, CodingKey { case the0 = "0" case the1 = "1" case the2 = "2" case the3 = "3" case the4 = "4" case id case itemID = "item_id" case attributeValue = "attribute_value" case variationPrice = "variation_price" case variationSaleprice = "variation_saleprice" case isCart = "is_cart" } }
2. 正确访问嵌套可选值
由于所有层级的属性都是可选类型,必须使用可选绑定或可选链安全访问,示例代码如下:
do { // 确保响应能正确转换为Data guard let responseDict = response as? [String: Any], let data = responseDict.toData() else { print("无法将响应转换为Data") return } let parseData = try JSONDecoder().decode(CategoryViewModel2.self, from: data) // 逐层遍历嵌套的可选数组,安全访问目标字段 parseData.data?.forEach { datum in datum.item?.forEach { item in item.variation?.forEach { variation in if let salePrice = variation.variationSaleprice { print("规格售价:\(salePrice)") } else { print("该规格无有效售价") } } } } } catch { print("解码失败:\(error.localizedDescription)") }
如果需要直接访问特定位置的元素,可使用多层可选绑定:
if let dataArray = parseData.data, let targetDatum = dataArray.first(where: { $0.id == 1 }), let items = targetDatum.item, let targetItem = items.first(where: { $0.id == 2 }), let variations = targetItem.variation, let halfVariation = variations.first(where: { $0.attributeValue == "Half" }), let halfSalePrice = halfVariation.variationSaleprice { print("Half规格售价:\(halfSalePrice)") }
关键注意事项
- 所有可选属性访问时必须处理
nil情况,避免运行时崩溃 - 结构体类型必须严格匹配JSON数据类型,尤其是数值类型(Int/Double)
- 不要直接对可选数组使用链式访问(如
data.item),需先解包数组或遍历元素
内容的提问来源于stack exchange,提问作者Kuldeep Vashist
相关产品推荐
相关产品推荐

