0
votes

When I try to decode JSON I get the error:

typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 1972", intValue: 1972), CodingKeys(stringValue: "song_name", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))

  1. JSON:
[
  {
    "song_id": 1373123,
    "song_name": "신라의 달밤",
    "artist": "현인",
    "album": "현인",
    "Like_count": 100,
    "Lyric": "아~ 신라의 밤이여\n불국사의 종소리 들리어 온다\n지나가는 나그네야 걸음을 멈추어라\n고요한 달빛 어린 금오산 기슭에서\n노래를 불러보자 신라의 밤 노래를\n\n아~ 신라의 밤이여\n아름다운 궁녀들 그리워라\n대궐 뒤에 숲 속에서 사랑을 맺었던가\n님들의 치맛소리 귓속에 들으면서\n노래를 불러보자 신라의 밤 노래를",
    "cover_url": "https://image.bugsm.co.kr/album/images/200/1134/113497.jpg?version=20170925032718.0"
  },
...
  1. Swift code
        let decoder = JSONDecoder()
        do {
            self.songs = try decoder.decode([Song].self, from: asset.data)
        } catch {
            print(error)
        }
  1. Model
struct Song: Codable {
//    var id: Int
    var title: String
    var artist: String
//    var album: String
//    var like: Int
//    var lylic: String
//    var coverURL: String
    
    enum CodingKeys: String, CodingKey {
//        case id = "song_id"
        case title = "song_name"
        case artist = "artist"
//        case album = "album"
//        case like = "Like_count"
//        case lylic = "Lyric"
//        case coverURL = "cover_url"
    }
}
1
Everything works with the JSON you posted. The error means that song_name was a number instead of string. Perhaps, in the real JSON there is sometimes an object with song_name being a number?New Dev

1 Answers

0
votes

The error is crystal clear: In the 1973rd item of the array (index 1972) the value for key song_name is a number. You have to add a custom initializer to fix the issue for example

struct Song: Decodable {
    let id : Int
    let title : String
    // ... other struct members

    enum CodingKeys: String, CodingKey {
        case id = "song_id"
        case title = "song_name"
    // ... other CodingKeys
    }        

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(Int.self, forKey: .id)
        do {
            self.title = try container.decode(String.self, forKey: .title)
        } catch {
            let numberName = try container.decode(Int.self, forKey: .title)
            self.title = String(numberName)
        }
        // other lines to initialize the other struct members
    }
}

If the error still persists the number could be also Double or Bool.