-1

I'm trying to write a Facebook Feed app for iOS, and I'm trying to use the JSON framework, to little effect. Whenever I run my code, I get the error "* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'". I'm using a feed from Flickr as a test/demonstration URL, as the Facebook URL is programmatically created using an Access Token request and appendToString:.

    NSURL *url2 = [NSURL URLWithString:@"www.flickr.com/services/feeds
                     /photos_public.gne?tags=punctuation&someKey=atsign&format=json"];
    NSError *error = nil;
    NSData *data = [NSData dataWithContentsOfURL:url2];
    if (data == nil){
        NSLog(@"data is nil");
    }
    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data 
                                                         options:NSJSONReadingMutableContainers
                                                          error:nil];
    NSLog(@"json: %@\n\n Or Error: %@", json, [error localizedDescription]);

EDIT: I changed my code around to include an error and an NSlog, and changed the URL (on the advice of the poster ilis), as well as adding an if statement to test if data is nil (thanks to poster Dustin for the idea). Now I get an output from the NSLog that states "json: (null) Or Error: The operation couldn't be completed. (Cocoa error 3840.)", and no response from the if statement. So I think the problem is arising when NSDictionary json is being created.

Chance
  • 33
  • 1
  • 8

3 Answers3

1

Your url is being incorrectly created. When you call dataWithContentsOfURL with a url that is invalid, you'll get a nil NSData. The JSON serialization method expects an NSData object but gets nil, so it throws NSInvalidArgumentException.

Nothing in your method looks incorrect, you just need to check that your URL is valid. It's a good idea to check that data is non-nil before you try to perform JSON serialization.

How to check if data is nil

if (data == nil)
{
     //handle the problem
}
else
{
     //You have valid content, do something with it
}
Dustin
  • 6,783
  • 4
  • 36
  • 53
  • How can I check that data is non-nil? Is there a better way than calling the description in NSLog? When I do that, it lags my machine pretty bad. Also, I've edited my question, could you take a look and see what you think might be wrong? – Chance Jul 31 '12 at 16:09
  • `NSLog` only gets used during debugging; when you distro your app it's not included, so lagging isn't a problem (although it's very odd that you are lagging because of an `NSLog`). Updating answer. – Dustin Jul 31 '12 at 16:18
  • Thanks for your response. I can't believe I didn't think of something that obvious! But when I added an if loop that sends an NSLog if data == nil, it doesn't fire the NSLog. So I guess the error is happening when I create the NSDictionary json? I'll update my question with the if statement test. – Chance Jul 31 '12 at 16:25
1

Flickr does some bad things with their JSON that the parser can't cope with:

  • they start with 'jsonFlickrFeed(' and end with ')'
    • this means that the root object is not valid
  • they incorrectly escape single quotes .. eg. \'
    • this is invalid JSON and will make the parser sad!

For those looking to process the Flick JSON feed

//get the feed
NSURL *flickrFeedURL = [NSURL URLWithString:@"http://api.flickr.com/services/feeds/photos_public.gne?format=json&tags=data"];
NSData *badJSON = [NSData dataWithContentsOfURL:flickrFeedURL];
//convert to UTF8 encoded string so that we can manipulate the 'badness' out of Flickr's feed
NSString *dataAsString = [NSString stringWithUTF8String:[badJSON bytes]];
//remove the leading 'jsonFlickrFeed(' and trailing ')' from the response data so we are left with a dictionary root object
NSString *correctedJSONString = [NSString stringWithString:[dataAsString substringWithRange:NSMakeRange (15, dataAsString.length-15-1)]];
//Flickr incorrectly tries to escape single quotes - this is invalid JSON (see http://stackoverflow.com/a/2275428/423565)
//correct by removing escape slash (note NSString also uses \ as escape character - thus we need to use \\)
correctedJSONString = [correctedJSONString stringByReplacingOccurrencesOfString:@"\\'" withString:@"'"];
//re-encode the now correct string representation of JSON back to a NSData object which can be parsed by NSJSONSerialization
NSData *correctedData = [correctedJSONString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:correctedData options:NSJSONReadingAllowFragments error:&error];
if (error) {
    NSLog(@"this still sucks - and we failed");
} else {
    NSLog(@"we successfully parsed the flickr 'JSON' feed: %@", json);
}
So Over It
  • 3,668
  • 3
  • 35
  • 46
0

I discovered the answer on StackOverflow: NSJSONSerialization.

Turns out that Flickr's JSON feed isn't properly formatted, so data was being populated with information that had a prefix on it that wasn't able to be handled by NSJSONSerialization.

Community
  • 1
  • 1
Chance
  • 33
  • 1
  • 8