lostAtSeaJoshua lostAtSeaJoshua - 3 months ago 30
Objective-C Question

How to parse JSONP in Objective-C?

I am retrieving JSON information for an API and it says on the API that it is in JSON but I noticed it is in JSONP or "json with padding" as some call it. I tired to look everywhere to find how to parse this but no luck. The information I am trying to receive is this:



({"book":[{"book_name":"James","book_nr":"59","chapter_nr":"3","chapter":
{"16":{"verse_nr":"16","verse":"For where envying and strife is, there is confusion and
every evil work."}}}],"direction":"LTR","type":"verse"});


The link to the data is https://getbible.net/json?p=James3:16, so you can look at it directly.

This is the code I am using to try to retrieve the JSON Data and parse it into a NSMutableDictionary.

-(void)fetchJson {
NSString *currentURL = [NSString stringWithFormat:@"https://getbible.net/json?p=James"];
NSURL *url = [NSURL URLWithString:currentURL];
NSData *data = [[NSData alloc]initWithContentsOfURL:url];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
NSMutableData *receivedData = [[NSMutableData alloc] initWithLength:0];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];

[receivedData setLength:0];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:@".json" expectedContentLength:-1 textEncodingName:nil];
expectedTotalSize = [response expectedContentLength];


if ([data length] !=0) {
NSLog(@"appendingData");
[receivedData appendData:data];

if(connection){
NSLog(@"Succeeded! Received %lu bytes of data",(unsigned long)[receivedData length]);
}

NSError *error;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

if(jsonResponse){
NSArray *responseArr = [jsonResponse mutableCopy];
NSLog(@"%lu",(unsigned long)[responseArr count]);
}else if (!jsonResponse){
//do internet connection error response
}
}
}


The results I am getting back from putting a breakpoint in the code is:


  • jsonResponse returns NULL

  • NSError NSCocoaErrorDomain code - 3840
  • but my NSData *data is returning 15640 bytes.


My console is displaying this from the NSLogs I used for debugging:

2014-04-20 01:27:31.877 appendingData
2014-04-20 01:27:31.879 Succeeded! Received 15640 bytes of data


I am receiving the data correctly but I am not parsing it correctly I know the error is because the JSON is in JSONP format. If anyone could please help with this I would appreciate it so much. I have tired to give as much detail on this question as I can but if you need more information just let me know so I can add it and make this as clear as possible.

Answer

Your code has at least two separate attempts to download the data. Neither is really correct. The code also only works with JSON, not JSONP.

Try this:

NSURL *url = [NSURL URLWithString:@"https://getbible.net/json?p=James"];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (data) {
        NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSRange range = [jsonString rangeOfString:@"("];
        range.location++;
        range.length = [jsonString length] - range.location - 2; // removes parens and trailing semicolon
        jsonString = [jsonString substringWithRange:range];
        NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

        NSError *jsonError = nil;
        NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonError];
        if (jsonResponse) {
            // process jsonResponse as needed
        } else {
            NSLog(@"Unable to parse JSON data: %@", jsonError);
        }
    } else {
        NSLog(@"Error loading data: %@", error);
    }
}];