给定的数据不是有效的JSON-在第二次搜索后发生

时间:2018-07-30 22:35:48

标签: ios swift

所以我有一个UICollectionView,一旦用户在搜索栏中输入一些文本,它就会显示图像。第一次效果很好,但是一旦您尝试再次搜索,您就会得到:

Failed to decode: dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})))

我检查了从请求发送的路径,它与应有的路径完全相同。看起来和第一个完全一样。我不明白这是怎么回事。...

模型类

import Foundation

struct Image{
    let name: String?
    let imageUrl: String?

    init(name: String? = nil, imageUrl: String? = nil) {
        self.name = name
        self.imageUrl = imageUrl
    }
}

struct ImageObject: Codable {
    let value: [Value]?
    let queryExpansions: [QueryExpansions]?
    let pivotSuggestions: [PivotSuggestions]?
    let similarTerms: [SimilarTerms]?
    let relatedSearches: [RelatedSearches]?
}

struct Value: Codable {
    let name: String?
    let contentUrl: String?
    let imageId: String?
    let thumbnailUrl: String?
}

struct QueryExpansions: Codable {
    let text: String?
    let thumbnail: ThumbnailWithUrl?
}

struct PivotSuggestions: Codable {
    let suggestions: [Suggestions]?
}

struct Suggestions: Codable {
    let text: String?
    let thumbnail: ThumbnailWithUrl?
}

struct SimilarTerms: Codable {
    let text: String?
    let thumbnail: Thumbnail?
}

struct RelatedSearches: Codable {
    let text: String?
    let thumbnail: ThumbnailWithUrl?
}

struct Thumbnail: Codable {
    let url: String?
}

struct ThumbnailWithUrl: Codable {
    let thumbnailUrl: String?
}

API_Service类

class API_Service{

static let sharedAPIService = API_Service()

func fetchImagesFromSearch(request: String ,completionHandler:@escaping(ImageObject?) ->()){
    var path = "https://api.cognitive.microsoft.com/bing/v7.0/images/search"
    let searchRequest = "q=" + request
    let array = [
        // Request parameters
        searchRequest,
        //"count=10",
        //"offset=0",
        "mkt=en-us",
        "safeSearch=Moderate",
        ]

    let string = array.joined(separator: "&")
    path = path + "?" + string

    guard let url = URL(string: path) else { return }
    var urlRequest = URLRequest(url: url)

    urlRequest.httpMethod = "GET"
    urlRequest.setValue("KeyGoesHere", forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
    urlRequest.httpBody = path.data(using: .utf8)

    URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
        if(error != nil){
            print("Error: \(error!)")
            completionHandler(nil)
        }

        guard let data = data else { return }

        do{
            let results = try JSONDecoder().decode(ImageObject.self, from: data)
            completionHandler(results)
        } catch let decodeError {
            // Decode error, what should we show to the user?
            print("Failed to decode: ", decodeError)
            completionHandler(nil)
        }
    }.resume()
}

}

ViewController类

import UIKit

class mainViewController: UIViewController, UICollectionViewDelegate, 
UICollectionViewDataSource, UISearchBarDelegate {

@IBOutlet weak var mainCollectionView: UICollectionView!
var images = [Image]()
let mainCollectionViewCellReusableIdentifier = "mainCollectionViewCell"
let searchController = UISearchController(searchResultsController: nil)

override func viewDidLoad() {
    super.viewDidLoad()

    setupLayout()
    setupSearchController()

    title = "Search something!"
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationItem.hidesSearchBarWhenScrolling = true
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func fetchImagesOf(searchText: String){
    API_Service.sharedAPIService.fetchImagesFromSearch(request: searchText) { (data) in
        if let results = data{
            if let values = results.value{
                self.collectImagesFromValue(using: values)
            }
            if let queryExpansions = results.queryExpansions{
                self.collectImagesFromQueryExpansions(using: queryExpansions)
            }
            if let pivotSuggestions = results.pivotSuggestions{
                self.collectImagesFromPivotSuggestions(using: pivotSuggestions)
            }
            if let similarTerms = results.similarTerms{
                self.collectImagesFromSimilarTerms(using: similarTerms)
            }
            if let relatedSearches = results.relatedSearches{
                self.collectImagesFromRelatedSearches(using: relatedSearches)
            }

            DispatchQueue.main.async {
                self.mainCollectionView.reloadData()
            }
        }
    }
}

func collectImagesFromValue(using results: [Value]){
    for image in results{
        if let url = image.thumbnailUrl{
            let name = image.name ?? ""
            let image = Image(name: name, imageUrl: url)
            self.images.append(image)
        }else{ continue }
    }
}

func collectImagesFromQueryExpansions(using results: [QueryExpansions]){
    for image in results{
        if let thumbnail = image.thumbnail{
            if let thumbnailUrl = thumbnail.thumbnailUrl{
                let name = image.text ?? ""
                let image = Image(name: name, imageUrl: thumbnailUrl)
                self.images.append(image)
            }else { continue }
        }else{ continue }
    }
}

func collectImagesFromPivotSuggestions(using results: [PivotSuggestions]){
    for image in results{
        if let suggestions = image.suggestions{
            for suggestion in suggestions{
                let name = suggestion.text ?? ""
                if let thumbnail = suggestion.thumbnail{
                    if let thumbnailUrl = thumbnail.thumbnailUrl{
                        let image = Image(name: name, imageUrl: thumbnailUrl)
                        self.images.append(image)
                    }
                }else { continue }
            }
        }else{ continue }
    }
}

func collectImagesFromSimilarTerms(using results: [SimilarTerms]){
    for image in results{
        if let thumbnail = image.thumbnail{
            if let thumbnailUrl = thumbnail.url{
                let name = image.text ?? ""
                let image = Image(name: name, imageUrl: thumbnailUrl)
                self.images.append(image)
            }else { continue }
        }else{ continue }
    }
}

func collectImagesFromRelatedSearches(using results: [RelatedSearches]){
    for image in results{
        if let thumbnail = image.thumbnail{
            if let thumbnailUrl = thumbnail.thumbnailUrl{
                let name = image.text ?? ""
                let image = Image(name: name, imageUrl: thumbnailUrl)
                self.images.append(image)
            }else { continue }
        }else{ continue }
    }
}

func setupLayout(){
    let layout = UICollectionViewFlowLayout()
    let cellHeight = view.frame.size.width / 3
    let cellWidth = cellHeight
    let cellSize = CGSize(width: cellWidth, height: cellHeight)

    layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    layout.itemSize = cellSize
    layout.minimumLineSpacing = 0
    layout.minimumInteritemSpacing = 0

    mainCollectionView.collectionViewLayout = layout
}

func setupSearchController(){
    searchController.searchBar.delegate = self
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.placeholder = "Search for images"

    navigationItem.searchController = searchController
    definesPresentationContext = true
    navigationItem.hidesSearchBarWhenScrolling = false
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    fetchImagesOf(searchText: searchBar.text!)
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return images.count > 0 ? images.count : 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: mainCollectionViewCellReusableIdentifier, for: indexPath) as! MainCollectionViewControllerCell
    if images.count > 0{
        cell.image = images[indexPath.row]
    }
    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    let imageViewController = storyBoard.instantiateViewController(withIdentifier: "imageViewController") as! ImageViewController
    imageViewController.image = images[indexPath.item]
    navigationController?.pushViewController(imageViewController, animated: true)
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

JSON

{
"_type": "Images",
"instrumentation": {
"_type": "ResponseInstrumentation"
},
"readLink": "https://api.cognitive.microsoft.com/api/v7/images/search? 
q=cats",
"webSearchUrl": "https://www.bing.com/images/search?q=cats&FORM=OIIARP",
"totalEstimatedMatches": 955,
"nextOffset": 5,
"value": [
{
  "webSearchUrl": "https://www.bing.com/images/search? view=detailv2&FORM=OIIRPO&q=cats&id=6B6E51236064B16189141D1916C6F188AB1D8FD1&simid=608039789623643813",
  "name": "Cute Cats #5 - Pets Cute and Docile",
  "thumbnailUrl": "https://tse2.mm.bing.net/th?id=OIP.U5GJh9jyKpFuhBIt_EEZvAHaE9&pid=Api",
  "datePublished": "2018-06-19T21:32:00.0000000Z",
  "contentUrl": "http://4.bp.blogspot.com/-o5XBs5uRifo/UIUQeuyqoMI/AAAAAAAAHm0/h-XH1IR3l6Y/s1600/cats_animals_cat_desktop_3872x2592_hd-wallpaper-863122.jpeg",
  "hostPageUrl": "http://dark-horse-adaptations.blogspot.com/2012/10/cute-cats-5.html",
  "contentSize": "127935 B",
  "encodingFormat": "jpeg",
  "hostPageDisplayUrl": "dark-horse-adaptations.blogspot.com/2012/10/cute-cats-5.html",
  "width": 1600,
  "height": 1071,
  "thumbnail": {
    "width": 474,
    "height": 317
  },
  "imageInsightsToken": "ccid_U5GJh9jy*mid_6B6E51236064B16189141D1916C6F188AB1D8FD1*simid_608039789623643813*thid_OIP.U5GJh9jyKpFuhBIt!_EEZvAHaE9",
  "insightsMetadata": {
    "recipeSourcesCount": 0,
    "bestRepresentativeQuery": {
      "text": "Crazy Cats Kittens Wallpaper",
      "displayText": "Crazy Cats Kittens Wallpaper",
      "webSearchUrl": "https://www.bing.com/images/search?q=Crazy+Cats+Kittens+Wallpaper&id=6B6E51236064B16189141D1916C6F188AB1D8FD1&FORM=IDBQDM"
    },
    "pagesIncludingCount": 32,
    "availableSizesCount": 16
  },
  "imageId": "6B6E51236064B16189141D1916C6F188AB1D8FD1",
  "accentColor": "666666"
},
{
  "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=F42DAAA598B5E0E1383CED35C292387266EB9A9F&simid=608030899010537949",
  "name": "A Cat’s Tale: Meowing for the right kind of food - Zee ...",
  "thumbnailUrl": "https://tse4.mm.bing.net/th?id=OIP.qtkOFD3PTouGYLHxi3xypwHaFj&pid=Api",
  "datePublished": "2017-06-12T03:21:00.0000000Z",
  "contentUrl": "http://zeelifestylecebu.com/wp-content/uploads/2015/03/cat3.jpg",
  "hostPageUrl": "http://zeelifestylecebu.com/a-cats-tale-meowing-for-the-right-kind-of-food/",
  "contentSize": "414235 B",
  "encodingFormat": "jpeg",
  "hostPageDisplayUrl": "zeelifestylecebu.com/a-cats-tale-meowing-for-the-right-kind-of-food",
  "width": 1600,
  "height": 1200,
  "thumbnail": {
    "width": 474,
    "height": 355
  },
  "imageInsightsToken": "ccid_qtkOFD3P*mid_F42DAAA598B5E0E1383CED35C292387266EB9A9F*simid_608030899010537949*thid_OIP.qtkOFD3PTouGYLHxi3xypwHaFj",
  "insightsMetadata": {
    "recipeSourcesCount": 0,
    "bestRepresentativeQuery": {
      "text": "Cat Kitten",
      "displayText": "Cat Kitten",
      "webSearchUrl": "https://www.bing.com/images/search?q=Cat+Kitten&id=F42DAAA598B5E0E1383CED35C292387266EB9A9F&FORM=IDBQDM"
    },
    "pagesIncludingCount": 46,
    "availableSizesCount": 20
  },
  "imageId": "F42DAAA598B5E0E1383CED35C292387266EB9A9F",
  "accentColor": "8E553D"
},
{
  "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56&simid=607997879302688190",
  "name": "cat | installect",
  "thumbnailUrl": "https://tse3.mm.bing.net/th?id=OIP.WpkNnHDGdlljW4b1G_cl-QHaF7&pid=Api",
  "datePublished": "2017-10-11T15:24:00.0000000Z",
  "contentUrl": "https://installect.files.wordpress.com/2013/03/catsincup.jpg",
  "hostPageUrl": "https://installect.wordpress.com/tag/cat/",
  "contentSize": "274870 B",
  "encodingFormat": "jpeg",
  "hostPageDisplayUrl": "https://installect.wordpress.com/tag/cat",
  "width": 1280,
  "height": 1024,
  "thumbnail": {
    "width": 474,
    "height": 379
  },
  "imageInsightsToken": "ccid_WpkNnHDG*mid_A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56*simid_607997879302688190*thid_OIP.WpkNnHDGdlljW4b1G!_cl-QHaF7",
  "insightsMetadata": {
    "recipeSourcesCount": 0,
    "bestRepresentativeQuery": {
      "text": "Cute Good Morning Kitten",
      "displayText": "Cute Good Morning Kitten",
      "webSearchUrl": "https://www.bing.com/images/search?q=Cute+Good+Morning+Kitten&id=A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56&FORM=IDBQDM"
    },
    "pagesIncludingCount": 420,
    "availableSizesCount": 116
  },
  "imageId": "A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56",
  "accentColor": "72441C"
},
{
  "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=8CC6B40382B19534E56CEE711488ED9FDAF52B93&simid=607994756864674280",
  "name": "Somali Cats – Jeanne Foguth's Blog",
  "thumbnailUrl": "https://tse3.mm.bing.net/th?id=OIP.Csfth4IIGILGI31QVA54HgHaHg&pid=Api",
  "datePublished": "2018-01-17T08:20:00.0000000Z",
  "contentUrl": "https://foguth.files.wordpress.com/2014/11/19068-chocolate-somali-cat-white-background.jpg",
  "hostPageUrl": "https://foguth.wordpress.com/tag/somali-cats/",
  "contentSize": "260846 B",
  "encodingFormat": "jpeg",
  "hostPageDisplayUrl": "https://foguth.wordpress.com/tag/somali-cats",
  "width": 1089,
  "height": 1104,
  "thumbnail": {
    "width": 474,
    "height": 480
  },
  "imageInsightsToken": "ccid_Csfth4II*mid_8CC6B40382B19534E56CEE711488ED9FDAF52B93*simid_607994756864674280*thid_OIP.Csfth4IIGILGI31QVA54HgHaHg",
  "insightsMetadata": {
    "recipeSourcesCount": 0,
    "bestRepresentativeQuery": {
      "text": "Chocolate Somali Cat",
      "displayText": "Chocolate Somali Cat",
      "webSearchUrl": "https://www.bing.com/images/search?q=Chocolate+Somali+Cat&id=8CC6B40382B19534E56CEE711488ED9FDAF52B93&FORM=IDBQDM"
    },
    "pagesIncludingCount": 12,
    "availableSizesCount": 4
  },
  "imageId": "8CC6B40382B19534E56CEE711488ED9FDAF52B93",
  "accentColor": "AF501C"
},
{
  "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=3FC937888C49B0641BC0A590AAF50FED74AEB93E&simid=608021153747308294",
  "name": "Cat Pictures - Photos of Cats | Interesting Stuff",
  "thumbnailUrl": "https://tse3.mm.bing.net/th?id=OIP.QjKAHyYfB4sQ9y_kbxEheAHaFA&pid=Api",
  "datePublished": "2011-10-29T23:41:00.0000000Z",
  "contentUrl": "http://www.cat-world.com.au/images/levi-sma2-big.jpg",
  "hostPageUrl": "http://www.cat-world.com.au/cat-photos",
  "contentSize": "800317 B",
  "encodingFormat": "jpeg",
  "hostPageDisplayUrl": "www.cat-world.com.au/cat-photos",
  "width": 1590,
  "height": 1075,
  "thumbnail": {
    "width": 474,
    "height": 320
  },
  "imageInsightsToken": "ccid_QjKAHyYf*mid_3FC937888C49B0641BC0A590AAF50FED74AEB93E*simid_608021153747308294*thid_OIP.QjKAHyYfB4sQ9y!_kbxEheAHaFA",
  "insightsMetadata": {
    "recipeSourcesCount": 0,
    "bestRepresentativeQuery": {
      "text": "Singapura Cat Breed",
      "displayText": "Singapura Cat Breed",
      "webSearchUrl": "https://www.bing.com/images/search?q=Singapura+Cat+Breed&id=3FC937888C49B0641BC0A590AAF50FED74AEB93E&FORM=IDBQDM"
    },
    "pagesIncludingCount": 24,
    "availableSizesCount": 12
  },
  "imageId": "3FC937888C49B0641BC0A590AAF50FED74AEB93E",
  "accentColor": "614B3D"
}
],

1 个答案:

答案 0 :(得分:0)

这是您遇到问题的代码段。

API_Service

urlRequest.httpMethod = "GET"
urlRequest.setValue("KeyGoesHere", forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
urlRequest.httpBody = path.data(using: .utf8)

您的httpMethod值为GET

但是,在下面的两行中您分配了一个httpBody值。

在执行GET请求时不使用该字段。通常用于在POST请求期间向API服务器发送诸如表单数据之类的信息。

删除设置正文的行,请求应该可以正常工作。