Error fetching interesting photos: invalidJSONData

I was able to get the JSON data to show in console initially but later in the chapter when it has me parse the data I keep getting an error instead of the photo count that it’s supposed to show. Code below. Any ideas what I’ve done wrong?

This is my FlickrAPI.swift file:

import Foundation

enum FlickrError: Error {
case invalidJSONData
}

enum Method: String {
case interestingPhotos = “flickr.interestingness.getList”
}

struct FlickrAPI {

private static let baseURLString = "https://api.flickr.com/services/rest"
private static let apiKey = "a6d819499131071f158fd740860a5a88"

private static let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    return formatter
}()

private static func flickrURL(method: Method, parameters: [String:String]?) -> URL {
    
    var components = URLComponents(string: baseURLString)!
    
    var queryItems = [URLQueryItem]()
    
    let baseParams = [
        "method": method.rawValue,
        "format": "json",
        "nojsoncallback": "1",
        "api_key": apiKey
    ]
    
    for (key, value) in baseParams {
        let item = URLQueryItem(name: key, value: value)
        queryItems.append(item)
    }
    
    if let additionalParams = parameters {
        for (key, value) in additionalParams {
            let item = URLQueryItem(name: key, value: value)
            queryItems.append(item)
        }
    }
    components.queryItems = queryItems
    
    return components.url!
}

private static func photo(fromJSON json: [String : Any]) -> Photo? {
    guard
        let photoID = json["id"] as? String,
        let title = json["title"] as? String,
        let dateString = json["dateTaken"] as? String,
        let photoURLString = json["url_h"] as? String,
        let url = URL(string: photoURLString),
        let dateTaken = dateFormatter.date(from: dateString) else {
            
            //don't have enough information to construct a photo
            return nil
    }
    
    return Photo(title: title, photoID: photoID, remoteURL: url, dateTaken: dateTaken)
}

static var interestingPhotosURL: URL {
    return flickrURL(method: .interestingPhotos, parameters: ["extra": "url_h,date_taken"])
}

static func photos(fromJSON data: Data) -> PhotosResult {
    do {
        let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
        
        guard
            let jsonDictionary = jsonObject as? [AnyHashable:Any],
            let photos = jsonDictionary["photos"] as? [String:Any],
            let photosArray = photos["photo"] as? [[String:Any]] else {
                
                //the json strucutre doesn't match our expectations
                return .failure(FlickrError.invalidJSONData)
        }
        
        var finalPhotos = [Photo]()
        for photoJSON in photosArray {
            if let photo = photo(fromJSON: photoJSON) {
                finalPhotos.append(photo)
            }
        }
        
        if finalPhotos.isEmpty && !photosArray.isEmpty {
            //we weren't able to parse any of the photos
            //maybe the json format for the photos has changed
            return .failure(FlickrError.invalidJSONData)
        }
        return .success(finalPhotos)
} catch let error {
    return .failure(error)
    }
}

}

Digging deeper into this, I’ve noticed that the JSON data I’m getting back from Flickr doesn’t match exactly with the parameters in my code. Here’s an example of what I get from Flickr:

photo = {
farm = 5;
id = 36161991222;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = “113231763@N07”;
secret = 405786f8d2
server = 4389
title = “La Lumo\U00e8re do sour (the code is longer but you get the idea)”

So I don’t have datetaken or url_h which is what my function is trying to pull.

Annnnd I’m an idiot.

I was missing an “s” on “extras” in the interestingPhotosURL function. Ugh.

the problem is in private static func photo, at line let dateString = json[“dateTaken”] as? String, you must replace “dateTaken” with “datetaken”

2 Likes

I elimininated any reference to dateTaken including “datetaken” in “extras”, since it was not present in the jsonObject, and I got an image.

This fixed it for me. Thanks