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

Swift中如何访问含可选值的嵌套JSON数据?

解决带可选属性的嵌套JSON数据访问问题

问题概述

已定义包含可选属性的Codable结构体,能成功解码API返回的嵌套JSON数据并在控制台打印结果,但存在两个问题:

  • 无法访问Variation2结构体中的variation_saleprice值
  • 尝试通过try JSONDecoder().decode(CategoryViewModel2.self, from: ...).data.item链式访问时,Xcode无法识别item变量

问题原因分析

  1. 类型不匹配导致解码失败:API返回的JSON中,variation_saleprice存在5.5这类浮点数值,但结构体Variation2中对应的variationSaleprice被定义为Int?类型,类型不匹配会导致该字段解码后为nil。
  2. 嵌套可选值的访问逻辑错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:05:13