Swift 4获取瑞典电台频道歌曲出错,结构体格式问题求助
Hey there! Let's work through fixing your JSON parsing issue when fetching current and previous songs from Swedish Radio channels in Swift 4. Since you suspect the problem lies in your Root and Playlist structs, and noted that Previous matches Song, we'll focus on aligning your structs with the actual API response and cleaning up redundant code first.
1. Match Your Structs Exactly to the JSON Schema
The most common cause of JSON parsing failures is a mismatch between your Swift structs and the API's JSON structure. First, make sure you know the exact shape of the JSON you're receiving. For example, if the API returns something like this:
{ "channels": [ { "id": 95, "name": "SR P1", "playlist": { "current": { "title": "Hälsa på dig", "artist": "Lisa Nilsson", "duration": 210 }, "previous": { "title": "Vem vet", "artist": "Cornelis Vreeswijk", "duration": 180 } } } ] }
Your structs should mirror this hierarchy exactly. Since Previous has the same fields as Song, you don't need a separate Previous struct—just reuse Song:
import Foundation // Reuse this for both current and previous songs struct Song: Codable { let title: String? let artist: String? let duration: Int? // Add any other fields present in the JSON } struct Playlist: Codable { let current: Song? let previous: Song? // No need for a separate Previous struct! } struct Channel: Codable { let id: Int? let name: String? let playlist: Playlist? } struct Root: Codable { let channels: [Channel]? }
2. Handle Optional Fields (And Avoid Unnecessary Optionals)
If some fields in the JSON might be missing (e.g., a channel might not have a previous song listed), mark those properties as optional with ?. If a field is always present, you can omit the ?—but be careful, as missing data will cause a parsing crash.
3. Use CodingKeys for Naming Mismatches
If the JSON uses snake_case (like song_title) but you prefer Swift's camelCase (songTitle), use CodingKeys to map them:
struct Song: Codable { let songTitle: String? let artistName: String? enum CodingKeys: String, CodingKey { case songTitle = "title" case artistName = "artist" } }
4. Debug with Error Logs
When parsing fails, print the full error message—it will tell you exactly what's wrong (e.g., missing key, type mismatch). Add this to your parsing code:
func fetchRadioChannels() { guard let url = URL(string: "YOUR_SWEDISH_RADIO_API_URL") else { return } URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { print("Network error: \(error?.localizedDescription ?? "Unknown error")") return } // Print raw JSON to verify structure if let jsonString = String(data: data, encoding: .utf8) { print("Raw JSON: \(jsonString)") } do { let decoder = JSONDecoder() // If the JSON uses snake_case, enable this: // decoder.keyDecodingStrategy = .convertFromSnakeCase let root = try decoder.decode(Root.self, from: data) // Access the parsed data if let channels = root.channels { for channel in channels { print("Channel: \(channel.name ?? "Unknown")") print("Current Song: \(channel.playlist?.current?.title ?? "None") by \(channel.playlist?.current?.artist ?? "Unknown")") print("Previous Song: \(channel.playlist?.previous?.title ?? "None") by \(channel.playlist?.previous?.artist ?? "Unknown")") } } } catch { print("Parsing error details: \(error)") // This will show you if a key is missing, or if a type doesn't match } }.resume() }
5. Double-Check the JSON Hierarchy
It's easy to mix up nested levels—for example, if playlist is inside a channel object, make sure your Channel struct has a playlist property, not your Root struct. The raw JSON printout from the code above will help you confirm the exact nesting.
By following these steps, you should be able to fix the parsing errors. The key is making sure your structs perfectly mirror the JSON's structure, reusing types where possible, and using error messages to pinpoint mismatches.
内容的提问来源于stack exchange,提问作者David Ruland

