I need to read a JSON file using the NSJSONSerialization Class Reference, and all the examples that I have found about the use of this class read the content from the webpage itself, instead of reading from a JSON file that has been previously created.Anyone knows how to parse from a JSON file using that class? Thanks.
Simple, quick'n'dirty example:
NSString *jsonPath = [[NSBundle mainBundle] pathForResource:#"foobar"
ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:jsonPath];
NSError *error = nil;
id json = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error];
NSLog(#"JSON: %#", json);
Related
I am trying to initialize an attributed string with HTML file contents, as following:
NSMutableAttributedString *attrStr = [[[NSAttributedString alloc] initWithFileURL:[NSURL fileURLWithPath:chapterPath]
options:#{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType}
documentAttributes:nil error:nil] mutableCopy];
and it does work with iOS7.1 and iOS8.1 and up, but something goes wrong with iOS8.0:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector
Is this initialization method broken in iOS8.0? Any workaround?
BTW, I have tried to parse an RTF file and, with iOS8.0, it fails to collect any font information.
Did you try this?.
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfFile:chapterPath options:NSDataReadingUncached error:&error];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData: data options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:&attributes error:nil];
Init with HTML for NSAttributedString is on main thread only. If you doing that in background be ready to crash.
I am getting data from the Yummly API and I would like to use it as though it were serialized JSON data. However, it is currently a string, and I cannot figure out how to turn it to data correctly. The code is as following:
NSString *searchParameters = #"basil"; //should be from text box
//NSError *error1 = nil;
NSString *searchURLName = [#"http://api.yummly.com/v1/api/recipes?_app_id=myAPIId&_app_key=myAPIkey&" stringByAppendingString:searchParameters];
NSURL *searchURL = [NSURL URLWithString:searchURLName];
NSString *searchResults = [NSString stringWithContentsOfURL:searchURL encoding:NSUTF8StringEncoding error:nil];
// Here, the search results are formatted just like a normal JSON file,
// For example:
/* [
"totalMatchCount":777306,
"facetCounts":{}
]
*/
// however it is a string, so I tried to convert it to data
NSData *URLData = [searchResults dataUsingEncoding:NSUTF8StringEncoding];
URLData = [URLData subdataWithRange:NSMakeRange(0, [URLData length] - 1)];
_searchArray = [NSJSONSerialization JSONObjectWithData:URLData options:NSJSONReadingMutableContainers error:nil];
Somewhere over the last four lines, it didn't do what it was supposed to and there is no data in the data object. Any advice or quick hints in the right direction are much appreciated! Thank you1
Look at the error being returned from the NSJSONSerialization object like
NSError *error;
_searchArray = [NSJSONSerialization JSONObjectWithData:URLData options:NSJSONReadingMutableContainers error:&error];
NSLog(#"%#", error);
This might give you a hint of what's wrong. This should work though.
And why exactly are you doing URLData = [URLData subdataWithRange:NSMakeRange(0, [URLData length] - 1)];? You don't need to copy the data, if that's why you're doing that.
Plus, it seems like you're assuming to get an array as the top level object (judging by
/* [
"totalMatchCount":777306,
"facetCounts":{}
]
*/
but this is a dictionary. Basically you probably want a dictionary, not array. This it should be
/* {
"totalMatchCount":777306,
"facetCounts":{}
}
*/
But the error getting returned will tell you that.
It looks like you're over-complicating things a bit. You do not need to bring in this data as an NSString at all. Instead, just bring it in as NSData and hand that to the parser.
Try:
NSString *searchParameters = #"basil"; //should be from text box
NSString *searchURLName = [#"http://api.yummly.com/v1/api/recipes?_app_id=myAPIId&_app_key=myAPIkey&" stringByAppendingString:searchParameters];
NSURL *searchURL = [NSURL URLWithString:searchURLName];
NSData *URLData = [NSData dataWithContentsOfURL:searchURL];
_searchArray = [NSJSONSerialization JSONObjectWithData:URLData options:NSJSONReadingMutableContainers error:nil];
Note that you'll want to verify that the parsed JSON object is indeed an array as expected, and is not/does not contain [NSNull null].
I want to parse json data which contains html but there is a problem
I made a parser with this lines but always I got this error: The operation couldn’t be completed. (Cocoa error 3840.)
NSString *str = [[NSString alloc] initWithData:responseObject encoding:NSASCIIStringEncoding];
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:dataoptions:NSJSONReadingMutableContainers error:&error];
You need to fix the incoming JSON object. You will need to encode that HTML in your web-service (whatever that may be). You should be able to see the issue when you run your JSON through a validator like JSONViewer or JSONLint.
I've read many Q/As on this problem but couldn't find an answer that fits my situation.
I retrieve a JSON response from a REST service I've created in PHP. This is my code:
NSURLResponse *response = nil;
NSError *theError1 = nil;
NSError *theError2 = nil;
NSURL *webServiceUrl = [NSURL URLWithString:#"http://..."];
NSURLRequest *request = [NSURLRequest requestWithURL:webServiceUrl cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30];
NSData *theData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&theError1];
NSString *dataString = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
NSLog(#"%#", dataString);
id json = [NSJSONSerialization JSONObjectWithData:theData options:NSJSONReadingAllowFragments | NSJSONReadingMutableContainers error:&theError2];
if (theError2 != nil)
NSLog(#"%#", theError2);
When I invoke the REST call in the browser, I see the following response, which seems identical to what XCode logs:
{
"Name": "REST Service",
"Product": "REST Test",
"Version": "1.0.0.0",
"Copyright": "2013 Test Company"
}
When I execute above code, however, the following error is created and logged:
Error Domain=NSCocoaErrorDomain Code=3840 "The data couldn’t be read because it has been corrupted." (Invalid value around character 3.) UserInfo=0x100547430 {NSDebugDescription=Invalid value around character 3.}
What am I doing wrong?
OK, as always, checking the actual data instead of the string representation pays - thanks #Bavarious.
It turns out that the PHP script(s) in charge of creating the JSON were all "UTF8 with BOM", so PHP returned a BOM for every script involved.
Once I changed all the PHP files to "UTF8 without BOM" everything seems to be fine - need to test this on the MAC though.
Sorry to interrupt, keep up the good work.
(#Bavarious: If you'd like to write an answer, I'd be happy to upvote and accept it, as you pointed me to the solution).
Was able to parse the JSON now as expected. Making a mental note to always double-check the text file encoding.
NSURL *theURL = [NSURL URLWithString:#"http://yourdataurl"];
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:theURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) {
NSError *error;
NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *theData = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:theData options:0 error:&error];
if (!jsonResponse || error)
{
NSLog(#"Error");
}
else
{
// Everything is ok..
}
}
}];
I'm trying to save a html page locally on the iPhone's documents directory so I can load the page if the phone is in an offline state
My issue is when I call my NSData object directly to be written to file all the raw data is saved in a file in the documents directory.
But as soon as I cast my NSData to a NSString using encoding it stops writing the file in the documents directory. But when I print my content object it logs out the correct data. I just want that to be saved to a file.
NSURL *url = [NSURL URLWithString:#"http://anyurl"];
NSData *urlHtmlData = [NSData dataWithContentsOfURL:url];
NSString *myString = [[NSString alloc]initWithData:urlHtmlData encoding:NSUTF8StringEncoding];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:#"index.html"];
[myString writeToFile:fileName atomically:NO encoding:NSStringEncodingConversionAllowLossy error:nil];
What could be causing the content to stop writing to my file?
Or if anyones got a better solution to view offline webpages rather than saving it to the documents directory?
Thanks
There could be a few things wrong with this. One: You don't use stringWithFormat: to append a path component. NSString has a method for that:
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:#"index.html"];
Two: NSStringEncodingConversionAllowLossy is part of an enum that is not defined for writeToFile:, so by using it, you're actually specifying NSASCIIStringEncoding without realizing it. In my opinion, just use NSUTF8StringEncoding instead.
Also, NSString *content = [[NSString alloc]initWithFormat:#"%#", myString]; does absolutely nothing except duplicate myString. Erase that line and just use [myString writeToFile:....