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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:17:08