Swift使用JSONDecoder报“No value associated with key”错误排查
问题根源:JSON结构与Swift解码结构体不匹配
你遇到的"No value associated with key"错误,核心原因是你的JSON数据嵌套层级和Swift结构体的期望完全不一致,解码器找不到对应字段,自然无法完成解析。
具体来说:
- 你的JSON中,
sections数组里的每一项都被包裹在"section"这个key下(比如{"section": {"title": "Main Settings", ...}}),但你的Section结构体直接期望顶级的title和items字段; - 同样,每个
items数组里的元素也被包裹在"item"key下(比如{"item": {"title": "Notifications", ...}}),但你的Item结构体直接期望顶级的title、type、url字段。
解决方法:二选一即可
方法1:修正JSON结构(推荐,更简洁)
直接去掉多余的嵌套包裹,让JSON结构和你的结构体完全对齐:
{ "sections": [ { "title": "Main Settings", "items": [ { "title": "Notifications", "type": "notification", "url": "" }, { "title": "Log Out", "type": "", "url": "" } ] }, { "title": "Feedback", "items": [ { "title": "Contact Us", "type": "email", "url": "" }, { "title": "Rate on App Store", "type": "webView", "url": "https://www.apple.com/uk/ios/app-store/" } ] }, { "title": "About", "items": [ { "title": "Terms of Service", "type": "webView", "url": "" }, { "title": "Privacy Policy", "type": "webView", "url": "https://www.apple.com/uk/ios/app-store/" }, { "title": "Version Info", "type": "webView", "url": "" } ] } ] }
修改后,你原来的Swift结构体(还可以删掉多余的CodingKeys,因为属性名和JSON key完全一致,Decodable会自动映射)就能正常解码了。
方法2:调整Swift结构体适配现有JSON
如果不能修改JSON,就需要给结构体添加中间层来匹配嵌套结构:
fileprivate struct SettingsPayload: Decodable { let sections: [SectionWrapper] // 用来包裹section的中间结构体 struct SectionWrapper: Decodable { let section: Section } } struct Section: Decodable { let title: String let items: [ItemWrapper] // 用来包裹item的中间结构体 struct ItemWrapper: Decodable { let item: Item } } struct Item: Decodable { let title: String let type: String let url: String }
然后解码时需要把中间层的实际数据提取出来:
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") { do { let data = try Data(contentsOf: url) let payload = try JSONDecoder().decode(SettingsPayload.self, from: data) // 提取实际的sections和items数据 let actualSections = payload.sections.map { wrapper in Section( title: wrapper.section.title, items: wrapper.section.items.map { $0.item } ) } completion(actualSections) } catch { print("解码错误:\(error)") completion(nil) } }
另外补充一点:你原结构体里的CodingKeys是多余的,因为属性名和JSON key完全一致,Swift的Decodable会自动完成映射,不需要手动声明。
内容的提问来源于stack exchange,提问作者Constantinos Theophilou
相关产品推荐
相关产品推荐

