代码之家  ›  专栏  ›  技术社区  ›  sk123

“应解码字符串,但找到了字典。”

  •  1
  • sk123  · 技术社区  · 6 年前

    (编码键在_AD7BA6EDB44A00F25A39B8A21DBEFF83中)。图像,基础。(_JSONKey在_12768CA107A31EF2DCE034FD75B541C9中)(stringValue:“索引0”,intValue:可选(0))],debugDescription:“应解码字符串,但找到了字典。”,underyingerror:nil))

    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()
            }
        }
    
    3 回复  |  直到 6 年前
        1
  •  3
  •   Ashley Mills    6 年前

    你的 image 类型不正确(错误消息告诉您这一点)。你把它当作 [String]

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

    然后

    let image: [Image]
    
        2
  •  2
  •   vadian    6 年前

    阅读 错误消息。很明显:键的值 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,根本不需要使用optionals

        3
  •  0
  •   Jogendar Choudhary    6 年前

    Array 属于 key-value pair(Dictionary) 所以你需要添加图像 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
        }
    
    }