如何在Objective-C中parsingJSONP?

我正在检索一个API的JSON信息,它说在API中,它是在JSON中,但我注意到它是在JSONP或“有填充的JSON”,有些人称之为。 我厌倦了四处寻找如何parsing这个,但没有运气。 我想收到的信息是这样的:

({"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"}); 

数据的链接是https://getbible.net/json?p=James3:16 ,所以你可以直接看它。

这是我正在使用的代码尝试检索JSON数据并将其parsing为一个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 } } } 

我从代码中放置一个断点的结果是:

  • jsonResponse返回NULL
  • NSError NSCocoaErrorDomain代码 – 3840
  • 但我的NSData *数据返回15640字节。

我的控制台显示这从我用于debugging的NSLogs:

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

我正确接收数据,但我没有正确parsing它我知道错误是因为JSON是在JSONP格式。 如果有人可以请帮忙,我会非常感激。 我已经厌倦了尽可能详细地提供这个问题,但如果你需要更多的信息,请让我知道,所以我可以添加它,并尽可能清楚。

您的代码至less有两次尝试下载数据。 两者都不是真的正确。 该代码也只适用于JSON,而不是JSONP。

尝试这个:

 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); } }]; 

一个问题是你下载的数据在开始和结束时都有无关的信息。 您的URL提供的JSON是:

 ({"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"}); 

正如您所看到的错误信息所示:您需要删除最初(从string的开始处); 从最后,所以你的JSON将从你的代码期望的字典开始。 你可以通过在你的NSData对象上调用subdataWithRange:来做到这一点:

 NSData* jsonData = [data subdataWithRange:NSMakeRange(1, data.length-3)]; NSDictionary* jsonResponse = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; 

为了更新每个人, NSURLRequest已经在iOS9中被弃用了。 我试了@rmaddy的答案,我也没有收到任何东西(就像@lostAtSeaJoshua遇到我猜)。 我已经更新了rmaddy的答案,以反映NSURLSession实现(我认为)取代NSURLRequest

  NSURLSession *session = [NSURLSession sharedSession]; NSURL *url = [NSURL URLWithString:@"http://somerandomwebsite.com/get.php?anotherRandomParameter=5"]; [[session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // handle response if (data) { NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"stringJSONed: %@",jsonString); //Do something with the received jsonString, just like in @ rmaddy's reply } else { NSLog(@"Error loading data: %@", error); } }] resume]; 

只是注意到,当我第一次运行它时,它给了我安全错误。 你需要做什么(如果你正在使用http)是把它添加到你的plist:

 <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> 

我不得不提到,在NSAllowArbitraryLoads键之后,最有可能的其他键和值,例如NSExceptionDomain 。 但是他们与我想的这个答案无关。 如果你需要更进一步,让我知道,我会深入挖掘:)