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

Swift中InstrumentsSet扩展的嵌套Track结构体单独加载JSON失败如何解决

问题结论

首先明确:你完全可以单独加载定义在扩展内的InstrumentsSet.Track结构体,当前的代码结构本身支持这种操作,解码失败是其他细节问题导致的。

核心原因排查&解决方案

  1. 首要问题:Track缺少Identifiable协议要求的id属性适配
    你声明了Track遵守Identifiable协议,该协议强制要求存在id属性。默认情况下Decodable会自动合成解码逻辑,尝试从JSON中读取id字段,而你提供的Track JSON中没有该字段,导致解码失败。
    解决方法:手动指定解码字段,排除id,并给id设置默认值:
extension InstrumentsSet {
    struct Track: Identifiable, Decodable {
        // 自动生成唯一id,无需从JSON解码
        let id = UUID()
        let instrumentType: InstrumentType
        let startType: StartType

        // 手动指定需要解码的字段,不包含id
        enum CodingKeys: String, CodingKey {
            case instrumentType, startType
        }
        
        // 原有withJSON方法保持不变即可
    }
}

同理你之前能成功解码InstrumentsSet,大概率是已经对InstrumentsSet的id做了类似适配,只需给Track做相同处理即可。

  1. 次常见问题:自定义枚举未适配Decodable
    检查InstrumentType和StartType两个自定义类型(通常为枚举),确保:
  • 明确遵守Decodable协议,比如字符串枚举声明为:
enum InstrumentType: String, Decodable {
    case exsSampler, audioBuffer
}
enum StartType: String, Decodable {
    case trigger, global
}
  • 枚举的case取值和JSON中的字符串完全一致,大小写、拼写都不能有差异。
  1. 调试技巧:不要吞掉解码错误
    你当前使用try?会直接忽略所有错误信息,无法定位具体问题,把解码逻辑改成do-catch打印错误即可快速定位根因:
static func withJSON(_ fileName: String) -> InstrumentsSet.Track? {
    guard let url = Bundle.main.url(forResource: fileName, withExtension: "json", subdirectory: "Sets") else { return nil }
    guard let data = try? Data(contentsOf: url) else { return nil }
    do {
        return try JSONDecoder().decode(InstrumentsSet.Track.self, from: data)
    } catch {
        // 控制台会输出精准的错误原因,比如缺字段、枚举值不匹配等
        print("解码失败:\(error)")
        return nil
    }
}

内容的提问来源于stack exchange,提问作者Frans-Jan Wind

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 10:39:05