Swift中YAML解析失败求助:类型不匹配错误排查
Swift Codable解析嵌套YAML时类型不匹配问题
问题描述
新增一段嵌套YAML数据到原本正常工作的YAML文件后,使用Swift Codable解析时出现类型不匹配错误,提示“Expected to decode Mapping but found Node”。目标是将该YAML映射到包含byTeam字段(类型为Dictionary<String, TeamChallenge>?)的CodableChallenge结构体中。
相关代码与错误信息
YAML代码
byTeam: - t0: { description: "Find a video of an object being selected and deselected", bestAnswer: [ 0 ]} - t1: { description: "Reveal and hide numeric controls", bestAnswer: [ 1 ]} - t2: { description: "Reveal and hide the tools", bestAnswer: [ 2 ]}
错误信息
no decode typeMismatch(Yams.Node.Mapping, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "assignments", intValue: nil), _YAMLCodingKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "challenges", intValue: nil), _YAMLCodingKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "byTeam", intValue: nil)], debugDescription: "Expected to decode Mapping but found Node instead.", underlyingError: nil))
Swift结构体定义
struct CodableChallenge : Codable { var title : String var type : String var description : String var uuid : UUID var videos : Array<String> var bestAnswer : Array<Int> var userAnswer : Array<Int>? var byTeam : Dictionary<String, TeamChallenge>? } struct TeamChallenge : Codable { var description : String var bestAnswer : Array<Int> }
解析代码
do { let decoded = try decoder.decode(MenuScreenVC.CodableCurriculum.self, from: src) manifestObsolete = curriculum == nil || decoded.referenceDate! > curriculum!.referenceDate! self.newManifest = decoded NotificationCenter.default.post(name: NSNotification.Name("gotManifest"), object: nil) return } catch { print("no decode \(error)") }
错误原因
当前YAML中的byTeam是数组类型(通过-标记元素列表),每个元素是独立的键值对字典;但Swift结构体中byTeam声明为Dictionary<String, TeamChallenge>?(单个字典类型),两者类型不匹配导致解析失败。
解决方案
有两种修复方式,可根据实际需求选择:
方式一:修改YAML结构匹配Swift字典类型
移除数组标记-,将byTeam改为直接的键值对集合:
byTeam: t0: { description: "Find a video of an object being selected and deselected", bestAnswer: [ 0 ]} t1: { description: "Reveal and hide numeric controls", bestAnswer: [ 1 ]} t2: { description: "Reveal and hide the tools", bestAnswer: [ 2 ]}
方式二:修改Swift结构体适配YAML数组类型
若需保留YAML的数组结构,将byTeam的类型改为数组包裹字典:
struct CodableChallenge : Codable { // 其他字段保持不变 var byTeam : Array<Dictionary<String, TeamChallenge>>? }
或更优雅的方式,定义单个键值对结构体后用数组包裹:
struct TeamEntry: Codable { var t0: TeamChallenge? var t1: TeamChallenge? var t2: TeamChallenge? } struct CodableChallenge : Codable { // 其他字段保持不变 var byTeam : Array<TeamEntry>? }
内容的提问来源于stack exchange,提问作者Dan Donaldson
相关产品推荐
相关产品推荐

