Ожидается декодирование String, но вместо этого нашел словарь.

Я пытаюсь расшифровать этот JSON, но пока не могу. Я пытаюсь перебрать массив альбомов и получить JSON, но сначала мне нужно просмотреть разные словари. Как я могу это исправить? Мне пришлось перейти от результатов к AlbumMatches и, наконец, к альбому, но он все еще ожидает словаря. Как я могу структурировать это и получить правильный формат?

Полная ошибка:

(CodingKeys в _AD7BA6EDB44A00F25A39B8A21DBEFF83) .image, Foundation. (_ JSONKey в _12768CA107A31EF2DCE034FD75B541C9) (stringValue: «Index 0», intValue: Optional (0) decocription: nexpected (0))], вместо debugDes ))

JSON:

{
  "results": {
    "opensearch:Query": {
      "#text": "",
      "role": "request",
      "searchTerms": "believe",
      "startPage": "1"
    },
    "opensearch:totalResults": "113802",
    "opensearch:startIndex": "0",
    "opensearch:itemsPerPage": "50",
    "albummatches": {
      "album": [
        {
          "name": "Believe",
          "artist": "Disturbed",
          "url": "https:\/\/www.last.fm\/music\/Disturbed\/Believe",
          "image": [
            {
              "#text": "https:\/\/lastfm-img2.akamaized.net\/i\/u\/34s\/bca3b80481394e25b03f4fc77c338897.png",
              "size": "small"
            },
            {
              "#text": "https:\/\/lastfm-img2.akamaized.net\/i\/u\/64s\/bca3b80481394e25b03f4fc77c338897.png",
              "size": "medium"
            }
          ],
          "streamable": "0",
          "mbid": "c559efc2-f734-41ae-93bd-2d78414e0356"
        },
        {
          "name": "Believe",
          "artist": "Justin Bieber",
          "url": "https:\/\/www.last.fm\/music\/Justin+Bieber\/Believe",
          "image": [
            {
              "#text": "https:\/\/lastfm-img2.akamaized.net\/i\/u\/34s\/899fe1643173a9568ac6e832327e7b57.png",
              "size": "small"
            },
            {
              "#text": "https:\/\/lastfm-img2.akamaized.net\/i\/u\/64s\/899fe1643173a9568ac6e832327e7b57.png",
              "size": "medium"
            }
          ],
          "streamable": "0",
          "mbid": "5d88ae0c-c4bf-4e64-bc97-45789880d910"
        }
}

Код:

struct SearchResults: Decodable {
    let results: Results
}

struct Results: Decodable {
    let albumMatches: AlbumMatches

    enum CodingKeys: String, CodingKey {
        case albumMatches = "albummatches"
    }
}

struct AlbumMatches: Decodable {
    let album: [Album]
}

struct Album: Decodable {
    let name: String?
    let image: [String]
    let artist: String?
}

class APIService {

    static let shared = APIService()

    func fetchArtists(searchText: String, url: URL, completionHandler: @escaping ([Album]) ->()) {
        Alamofire.request(url, method: .get, encoding: URLEncoding.default, headers: nil).responseData { (dataResponse) in
            if let error = dataResponse.error {
                print("Failed to contact last fm", error)
                return
            }

            guard let data = dataResponse.data else { return }

            do {
                let decoder = JSONDecoder()
                let searchResult = try decoder.decode(SearchResults.self, from: data)
                searchResult.results.albumMatches.album.forEach({ (album) in
                    print(searchResult.results.albumMatches.album)
                })

            } catch let decodeError {
                print("Failed to decode", decodeError)
            }
        }

    }
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        print(searchText)
        let baseLastfmUrl = "http://ws.audioscrobbler.com/2.0/?method=album.search&album=believe&api_key=MyKey&format=json"
        guard let url = URL(string: baseLastfmUrl) else { return }

        APIService.shared.fetchArtists(searchText: searchText, url: url) { (album) in
            self.albums = album
            self.tableView.reloadData()
        }
    }

person sk123    schedule 30.09.2018    source источник


Ответы (3)


Ваш image тип неверен (сообщение об ошибке сообщает вам об этом). У вас это как [String], когда должно быть ...

struct Image { 
    let text: URL 
    let size: String 

    enum CodingKeys: String, CodingKey {
        case text = "#text", size
    }      
 }

а потом

let image: [Image]
person Ashley Mills    schedule 30.09.2018

Прочтите сообщение об ошибке. Это очень ясно: значение ключа image - это массив словарей, а не массив строк.

Словарь декодируется в структуру, поэтому создайте структуру Image, и я рекомендую декодировать text как URL и size как перечисление

struct Album: Decodable {
    let name: String
    let image: [Image]
    let artist: String
}

enum ImageSize : String, Decodable {
    case small, medium, large
}

struct Image : Decodable {
    private enum CodingKeys: String, CodingKey { case  text = "#text", size }

    let text : URL
    let size : ImageSize
}

И согласно данному JSON вообще нет необходимости использовать опциональные параметры.

person vadian    schedule 30.09.2018

Согласно вашему ответу, изображение имеет Array из key-value pair(Dictionary), поэтому вам нужно добавить объект Image struct, как показано ниже (в настоящее время вы добавили [String], но вам нужно добавить [[String: String]])

"image": [
            {
              "#text": "https:\/\/lastfm-img2.akamaized.net\/i\/u\/34s\/899fe1643173a9568ac6e832327e7b57.png",
              "size": "small"
            },
            {
              "#text": "https:\/\/lastfm-img2.akamaized.net\/i\/u\/64s\/899fe1643173a9568ac6e832327e7b57.png",
              "size": "medium"
            }
          ]

struct Album: Decodable {
    let name: String?
    let image: [[String:String]]
    let artist: String?
}

ИЛИ (рекомендуется второй способ)

Вы можете создать для этого еще одну структуру, как показано ниже:

struct Album: Decodable {
    let name: String?
    let image: [Images]
    let artist: String?
}
struct Images: Decodable {
    let text: String?
    let size: String?

    enum CodingKeys: String, CodingKey {
    case text = "#text"
    case size
    }

}
person Jogendar Choudhary    schedule 30.09.2018
comment
У вас должен быть struct Image { let text: URL let size: String } - person Ashley Mills; 30.09.2018
comment
@AshleyMills: я добавил оба ответа - person Jogendar Choudhary; 30.09.2018