ios5 - JSON Parsing - dictionary OK, not parsing to array - json

I am using the new ios5 "NSJSONSerialization" function to obtain some tech-news from a website. I seem to have everything working OK, up until the point when I try to parse the NSDictionary into an NSArray. I have included the code here. The first console test (test 1) is working great - I get a console full of returned json data. But at the second console test (test 2 - the one that checks the contents of the nsarray), gives this message: "Array returned: (null)". Any ideas? Is it because I reused the error variable, maybe? I'm stumped.
Here's the code:
// create the string for making the api call to the website
NSString* theURL = [NSString stringWithFormat:#"http://pipes.yahoo.com/pipes/pipe.run?_id=9DfJELfJ2xGnjAQWJphxuA&_render=json"];
// declare and assign variables necessary to generate the actual url request
NSError* err = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:theURL];
[request setURL:URL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:30];
// make the actual url request - get the data from yahoo pipes, in json format
NSData* jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
// assign the entire result to a dictionary
NSDictionary *resultsDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&err];
//*** test 1: use the console to test results:
NSLog(#"NSDictionary returned: %#",resultsDictionary);
// parse the whole returned list of items (in dictionary form) into a large array
NSArray* arrayOfReturnedItems = [resultsDictionary objectForKey:#"items"];
//*** test 2: view the items returned (in the console)
NSLog(#"Array returned: %#",[arrayOfReturnedItems objectAtIndex:0]);

Related

NSJSONSerialization not handling negative integers

I’m trying to parse an JSON file into an NSArray and it all works well for positive numbers. However all the negative integers in that JSON file produce high numbers like “[11] __NSCFNumber * (long)72057594037927933”. How can i get that to work?
Here is my JSON file:
[0,1,2,3,4,5,6,7,8,9,10,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11]
and here the code:
NSError* error;
NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://some/json/file.json"]];
NSMutableArray* array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
Xcode doesn't always print nice values into the Debug area of the Xcode (where live values for the context appear).
I dropped your code into my own project and when I step through each line, I do see the "eachNumber __NSCFNumber * (long)72057594037927934 {0xbfffffffffffffe3} bits, but if I try print out the values of the array into the console, you'll see the correct "-2" result.
Try it yourself. I added in these lines right after yours:
NSMutableArray* array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSLog(#"array is %#", array);
for(id eachNumber in array)
{
NSLog(#"eachNumber is %#", eachNumber);
}

Converting NSString to NSData for use in XCODE

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].

Trouble loading data for TableView from server

Im using a web-service API to load information from a DB (mySQL). When transitioning to a UITableViewController, I retrieve an array that contains categories in the VieDidLoad method. However, I am not able to display the array of categories that I got into the table view cells. When I init the category NSMutubaleArray and hardcode it on the otherhand, the tableview does display the information. I am trying to understand what I'm doing wrong in the steps of loading this array and populating it onto the tableview. Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
//When I init the _categoryList the way below, it displays the info.
//_categoryList = [[NSMutableArray alloc] initWithObjects:#"Trending",#"Sports",#"Portraits", #"Art",#"IdUser", nil];
_toCategory = [[NSString alloc]init];
//When I try to populate it from the server it doesnt work.
_categoryList = [[NSMutableArray alloc]init];
//just call the "getCategories" command from the web API
[[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"getCategories",#"command",
nil]
onCompletion:^(NSDictionary *json) {
//got stream
NSArray *tempArray = [json objectForKey:#"result"];
for (int i=0;i<tempArray.count;i++){
[_categoryList insertObject:[tempArray objectAtIndex:i] atIndex:i];
}
//I verify that I was able to retrieve the array with the correct conent.
[self printArray:_categoryList];
NSLog(#"got categories");
[self.tableView reloadData];
}];
}
Any help would be greatly appreciated. Thanks!
UPDATE #1:
The JSON return is an array with NSDictioanry's. I print out its contents just to make sure, by calling the JsonArray objectForKey[‘categories’] and get this:
SwiphtMVPClone[2410:11303] Array at Index 0 = Trending
SwiphtMVPClone[2410:11303] Array at Index 1 = Sports
SwiphtMVPClone[2410:11303] Array at Index 2 = Portraits
SwiphtMVPClone[2410:11303] Array at Index 3 = Art
Right now, my app is actually crashing – getting this error:
[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance 0x72a85d0

iOS Parsing JSON Woes

I've been bashing my head against a wall for a bit.
I have a rails back-end that is returning JSON to my iOS app. I'm using rails' default return for rendering my object in JSON for me automatically. I'm having trouble with the errors it returns.
The JSON I get for errors is {"errors":{"email":["can't be blank"],"password":["can't be blank"]}}.
I use ASI for handling the request.
-(void) requestFinished:(ASIFormDataRequest *)request {
NSDictionary *data = [[request responseString] JSONValue];
Doing the above code make data become:
{
errors =
{
email = (
"can't be blank"
);
password = (
"can't be blank"
);
};
}
Now this gives me issues trying to parse it out. I'd like to be able to access each element of errors, and its associated value.
When I try to loop through the elements, I do something like:
for (NSDictionary *error in [data objectForKey:#"errors"])
This will give me email and password, but they are of type __NSCFString, not NSDictionary. I haven't been able to find a way to get the value for either email or password. Does anyone have an idea on how to parse this out?
Thanks!
This should work, note that response has the same structure than your 'data' NSDictionary.
NSDictionary *fields = [[NSDictionary alloc] initWithObjectsAndKeys: [[NSArray alloc] initWithObjects:#"one", #"two", nil],
#"A",
[[NSArray alloc] initWithObjects:#"three", #"four", nil],
#"B",
nil];
NSDictionary *response = [[NSDictionary alloc] initWithObjectsAndKeys:fields, #"errors", nil];
NSLog(#"Dictionary: %#", [response objectForKey:#"errors"]);
for (NSString *field in [response objectForKey:#"errors"])
for (NSString* error in [response valueForKeyPath:[NSString stringWithFormat:#"errors.%#", field]])
NSLog(#"%# %#", field, error);
The output will look like this:
Dictionary: {
A = (
one,
two
);
B = (
three,
four
);
}
A one
A two
B three
B four
Well i dont have Mac right now but i'm trying to help you if it doesnt work let me know i will correct it tomorrow.
-(void) requestFinished:(ASIFormDataRequest *)request
{
NSArray *data = [[request responseString] JSONValue];
NSDictionary *dict = [data objectAtIndex:0];
NSDictionary *dict2 = [dict valueForKey:#"errors"];
NSLog(#"email = %#, password = %#",[dict2 valueForKey:#"email"], [dict2 valueForKey:#"password"]);
}

ios5: Sending JSON data from the iPhone to REST using POST

I am trying to send data in the JSON format to the REST api. When sending a parameter the web service does not return any data but instead gives the following error:Error parsing JSON: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.)
This is because the parameter cannot be read by the web service.
But if I add this parameter directly to the URL the correct results are returned Eg:http://localhost:8080/de.vogella.jersey.final/rest/notes/63056
The following is the code for sending the parameters:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://localhost:8080/de.vogella.jersey.final/rest/notes/"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSString *postString = #"{\"notes\":\"63056\"}";
NSLog(#"Request: %#", postString);
// NSString *postString = #"";
[request setValue:[NSString stringWithFormat:#"%d",[postString length]] forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil ];
NSLog(#"Return Data%#",returnData);
//Getting the task types from the JSON array received
NSMutableArray *jsonArray =[NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
NSLog(#"jsonArray is %#",jsonArray);
taskTypes =[[NSMutableArray alloc]init ];
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#",error);
} else {
for(NSDictionary *taskType in jsonArray) {
[taskTypes addObject:[taskType objectForKey:#"TaskName"]];
}
}
Any suggestions?
Your error "JSON text did not start with array or object and option to allow fragments not set" could mean two things:
You're specifying that you expect the response object to be in JSON format and it is not (for example, this would happen if you're using an AFJSONRequestOperation and the server returns something other than JSON)
Fix: Get a hold of the server code and make sure it returns a valid JSON object
You have not specified that you're okay with receiving something other than JSON
Fix: If you're using AFNetworking, pass in NSJSONReadingAllowFragments to [NSJSONSerialization JSONObjectWithData:options:error:] on your subclass of AFHTTPClient (Shout out to Cocoa error 3840 using JSON (iOS) for this answer).