iOS Parsing JSON Woes - json

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

Related

stringByReplacingOccurrencesOfString not functioning correctly

I created a small app which will get html from website and turn that into string. Now I want to delete some text from that string but it is not deleting that text. Here is my code that I wrote.
-(void)dk {
NSString *myURLString = #"http://bountyboulevardss.eq.edu.au/?cat=3&feed=rss2";
NSURL *myURL = [NSURL URLWithString:myURLString];
NSError *error = nil;
NSString *myHTMLString = [NSString stringWithContentsOfURL:myURL encoding: NSUTF8StringEncoding error:&error];
[myHTMLString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if (error != nil)
{
NSLog(#"Error : %#", error);
}
else
{
}
[myHTMLString stringByReplacingOccurrencesOfString:#"<title>Bounty Boulevard » » Latest News</title>" withString:#""];
NSString *newString = myHTMLString;
NSScanner *scanner = [NSScanner scannerWithString:newString];
NSString *token = nil;
[scanner scanUpToString:#"<title>" intoString:NULL];
[scanner scanUpToString:#"</title>" intoString:&token];
headline.text = token;
NSLog(#"%#", myHTMLString);
}
Like you see in the beginning I try to delete the first title in the text and then I scan for the title I still keep getting the title I deleted. I checked in log and it is not deleting. I don't know what I am doing wrong. Sorry guys if this is really easy. Thanks for helping.
Not an Objective-C expert myself, but I guess you need to assign the replaced value back to the variable:
myHTMLString = [myHTMLString stringByReplacingOccurrencesOfString:#"<title>Bounty Boulevard » » Latest News</title>" withString:#""];
So, in general the idiomatic way to replace a string and keeping the result in the same variable is:
str = [str stringByReplacingOccurrencesOfString....];
This is confirmed by the stringByReplacingOccurencesOfString doc which states that this method "returns a new string in which all occurrences of a target string in the receiver are replaced by another given string.".

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

Parsing JSON with NSJSONSerialization: Error 3840 - Data Corrupted?

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

Fast Enumeration in parse

I'm new to iOS and I'm trying to parse out JSON data. Nothing will log from inside of the enumeration, though vehicleActivity logs "vehicle (null).I am interested in logging the "LineRef" data. I'm assuming it is in NSString, but I tried with id object and still nothing.
NSDictionary *jsonParse = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
NSArray * vehicleActivity = [jsonParse objectForKey:#"VechicleActivity"];
NSLog(#"vehicle %#",vehicleActivity);
for (NSDictionary *dictionary in vehicleActivity ) {
NSDictionary *monitoredVehJourney = [dictionary objectForKey:#"MonitoredVehicleJourney"];
NSString *line = [monitoredVehJourney objectForKey:#"LineRef"];
NSLog(#"Line # %#",line);
Here is the JSON through a viewer
Thanks
though vehicleActivity logs "vehicle (null)"
That's why. If vehicleActivity is NULL (i. e., nil), then the fast enumeration wouldn't even begin.
Furthermore, you seem not to have read the documentation of the NSDictionary class. It iterates through keys, not values. So your for loop should be
for (NSString *key in vehicleActivity ) {
NSDictionary *dictionary = [vehicleActivity objectForKey:key];
// etc.
}
instead.
Furthermore, I believe you have a typo in your code regarding the key VehicleActivity. You wrote it as VechicleActivity.

I use JSON but there is exception [NSString objectForKey:]

i read information in my database i use JSON but there is exception
'NSInvalidArgumentException', reason: '-[NSCFString objectForKey:]: unrecognized selector sent to instance 0x603dfb0'
I think this part :
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *str = [[[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding] autorelease];
NSArray *array = [str JSONValue];
if (!array)
return;
NSDateFormatter *fmt = [[[NSDateFormatter alloc] init] autorelease];
[fmt setDateFormat:#"yyyy-MM-dd"];
for (NSDictionary *dict in array) {
NSDate *d = [fmt dateFromString:[dict objectForKey:#"eve_date"]];
NSLog(#"%#",d);
[eventPHP addObject:[Events eventsNamed:[dict objectForKey:#"title_event"] description:[dict objectForKey:#"description"] date:d]];
}
}
"pass the linker a special flag, ‘-ObjC’. Adjusting the build settings of my project to include this flag in the ‘Other linker flags’"
according to:
http://beatworm.co.uk/blog/computers/using-categories-on-objective-c-classes-in-a-static-library/
EDIT:
Why it is terminating?
EDIT2:
OK, not exactly sure (as I've never done this type of coding), but given the json data:
{"event":[
{"eve_date":"2011-12-18","eve_time":"00:00:06","title_event":"Google event","description":"Google event for IT student"},
{"eve_date":"2011-12-29","eve_time":"00:00:08","title_event":"microsoft event","description":"microsoft event for IT student"}
]}
The first object is an array labeled "event" which might be throwing you off.
So, try replacing this:
for (NSDictionary *dict in array) {
NSDate *d = [fmt dateFromString:[dict objectForKey:#"eve_date"]];
NSLog(#"%#",d);
[eventPHP addObject:[Events eventsNamed:[dict objectForKey:#"title_event"] description:[dict objectForKey:#"description"] date:d]];
}
with:
NSArray *array2 = [array objectForKey:#"event"];
for (NSDictionary *dict in array2) {
NSDate *d = [fmt dateFromString:[dict objectForKey:#"eve_date"]];
NSLog(#"%#",d);
[eventPHP addObject:[Events eventsNamed:[dict objectForKey:#"title_event"] description:[dict objectForKey:#"description"] date:d]];
}
using: Problem getting JSON contents with JSONValue
Not sure if that will work, but if it does, it will make more sense to me.
I solve exception by change location files class of JSON but the event doesn't
display in calendar .
the calendr is display but didn't contain any event
hint: when i put url in browser the content of database display