Swift 4获取各频道歌曲报错:Root与Playlist结构体格式问题求助
修复Swift 4中JSON解析Root/Playlist结构体的异常问题
我当初刚学Swift JSON解析的时候也踩过不少结构体匹配的坑,太懂这种明明结构看起来一致却报错的痛苦了!结合你说的Previous和Song结构一致的情况,咱们一步步排查修复:
1. 先搞清楚「JSON结构」和「Swift结构体」的匹配度
这是最容易出错的核心点,你可以先把API返回的原始JSON打印出来,逐层级对比:
- 属性名大小写/拼写必须完全对应:Swift 4默认大小写敏感,比如JSON里是
"songTitle",你结构体里写song_title就会直接解析失败。如果不想改属性名,就用CodingKeys做映射:struct Song: Codable { let songTitle: String let artistName: String // 用CodingKeys映射JSON的key enum CodingKeys: String, CodingKey { case songTitle = "song_title" case artistName = "artist_name" } } - 可选值标记不能漏:如果JSON里某个字段可能为
null(比如有些频道可能还没有上一首歌曲),结构体里对应的属性必须加?,比如let previousSong: Song?,否则会因为缺失值报错。 - 直接复用Song结构体,删掉Previous:既然你说两者结构完全一致,没必要单独定义
Previous,直接在Playlist里用Song类型就行,既减少冗余,也避免不小心写出不一致的结构。
2. 验证Root和Playlist的嵌套层级
举个实际的例子,假设你的API返回JSON是这样的:
{ "playlist": { "current_song": { "title": "Hello", "artist": "Adele" }, "previous_song": { "title": "Rolling in the Deep", "artist": "Adele" } } }
那对应的正确Swift结构体应该是:
// 最外层的Root结构 struct Root: Codable { let playlist: Playlist } // 播放列表结构 struct Playlist: Codable { let currentSong: Song let previousSong: Song? // 上一首可能为空,加可选标记 enum CodingKeys: String, CodingKey { case currentSong = "current_song" case previousSong = "previous_song" } } // 歌曲结构(同时复用给当前和上一首) struct Song: Codable { let title: String let artist: String }
3. 捕获具体的解析错误信息
别只知道“解析失败”,把错误详情打出来,能直接定位问题:
// 假设你已经拿到了JSON数据jsonData do { let decodedData = try JSONDecoder().decode(Root.self, from: jsonData) print("当前歌曲:\(decodedData.playlist.currentSong.title)") if let prevSong = decodedData.playlist.previousSong { print("上一首歌曲:\(prevSong.title)") } } catch let decodingError { print("解析错误详情:\(decodingError)") // 错误信息会明确告诉你是key找不到、类型不匹配还是层级错误 }
比如如果报错keyNotFound(CodingKeys(stringValue: "current_song", intValue: nil)...,那就是Playlist里的currentSong对应的JSON key写错了,直接修正就行。
4. 最后检查几个常见小坑
- 别把数组和字典搞混:如果JSON里是数组(比如
"songs": [...]),结构体里必须写成let songs: [Song],不能写成字典类型。 - 数值类型要匹配:比如JSON里的
duration是数字180,结构体里不能写成String类型,必须用Int或Double。 - 所有嵌套结构体都要遵循
Codable:Swift 4会自动给属性都符合Codable的结构体合成实现,但如果手动写了init(from:),要确保所有属性都正确解码。
内容的提问来源于stack exchange,提问作者David Ruland
相关产品推荐
相关产品推荐

