Ошибка несоответствия типа декодера JSON в Swift

#ios #json #swift

#iOS #json #swift

Вопрос:

Когда я пытаюсь декодировать JSON, я получаю сообщение об ошибке:

Несоответствие типов (Swift.Строка, Swift.Ошибка декодирования.Context(codingPath: [_JSONKey(stringValue: «Index 1972», intValue: 1972), CodingKeys(stringValue: «song_name», intValue: nil)], debugDescription: «Ожидалось декодировать строку, но вместо этого найдено число.», underlyingError: nil))

  1. JSON:
 [
  {
    "song_id": 1373123,
    "song_name": "신라의 달밤",
    "artist": "현인",
    "album": "현인",
    "Like_count": 100,
    "Lyric": "아~ 신라의 밤이여n불국사의 종소리 들리어 온다n지나가는 나그네야 걸음을 멈추어라n고요한 달빛 어린 금오산 기슭에서n노래를 불러보자 신라의 밤 노래를nn아~ 신라의 밤이여n아름다운 궁녀들 그리워라n대궐 뒤에 숲 속에서 사랑을 맺었던가n님들의 치맛소리 귓속에 들으면서n노래를 불러보자 신라의 밤 노래를",
    "cover_url": "https://image.bugsm.co.kr/album/images/200/1134/113497.jpg?version=20170925032718.0"
  },
...
  
  1. Код Swift
         let decoder = JSONDecoder()
        do {
            self.songs = try decoder.decode([Song].self, from: asset.data)
        } catch {
            print(error)
        }
  
  1. Модель
 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. Все работает с опубликованным вами JSON. Ошибка означает, что song_name это было число вместо строки. Возможно, в реальном JSON иногда есть объект с song_name числом?

Ответ №1:

Ошибка предельно ясна: в 1973-м элементе массива (индекс 1972) значением для ключа song_name является число. Вы должны добавить пользовательский инициализатор, чтобы устранить проблему, например

 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
    }
}
  

Если ошибка все еще сохраняется, число также может быть Double или Bool .

Комментарии:

1. Когда мы указываем тип как необязательный, он по-прежнему не анализирует JSON, в идеале он должен анализировать с нулевым значением для данных, которые он не смог проанализировать. Например, структура песни: декодируемая { пусть идентификатор: Int пусть заголовок: Строка? } поэтому, когда мы декодируем, он должен иметь значение в идентификаторе, но не в названии. но возникает ошибка, не удается проанализировать JSON. Как это исправить без сбоя приложения