displaying JSON data with the help of dictionaries and array - nsdictionary

I get the following error
[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x75a8e20
2013-04-20 08:56:14.90 MyApp[407:c07] *** Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]:
unrecognized selector sent to instance 0x75a8e20'
This is my first hands on working with JSON. I get the above mentioned error when I try to run the first piece of code where URL is a flickr url. When I use the photos as key it print the array and app abruptly quits.
#define flickrPhotoURL [NSURL URLWithString: #"http://api.flickr.com/services/rest/?format=json&sort=random&method=flickr.photos.search&tags=rocket&tag_mode=all&api_key=12345&nojsoncallback=1"]
- (void)viewDidLoad
{
[super viewDidLoad];
//this line of code will be executed in the background to download the contents of the flickr URL
dispatch_async(flickrBgQueue, ^{
NSData* flickrData = [NSData dataWithContentsOfURL:flickrPhotoURL]; //NOTE: synchronous method...But we actually need to implement asynchronous method
[self performSelectorOnMainThread:#selector(appFetchedData:) withObject:flickrData waitUntilDone:YES]; //when data is available "appFetchedData" method will be called
});
}
- (void)appFetchedData: (NSData *)responseData
{
//parsing JSON data
NSError *error_parsing;
NSDictionary *flickr_json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error_parsing];
NSArray* photo_information = [flickr_json objectForKey:#"photos"];
NSLog(#"Photo Information: %#",photo_information);
NSDictionary* photo = (NSDictionary*)[photo_information objectAtIndex:0];
humanReadable.text = [NSString stringWithFormat:#"Owner is %#",[photo objectForKey:#"Owner"]];
}
However when I run the same piece of code by replacing the key "photos" with "loans" and use the following URL and code
#define flickrPhotoURL [NSURL URLWithString: #"http://api.kivaws.org/v1/loans/search.json?status=fundraising"]
- (void)appFetchedData: (NSData *)responseData
{
//parsing JSON data
NSError *error_parsing;
NSDictionary *flickr_json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error_parsing];
NSArray* photo_information = [flickr_json objectForKey:#"loans"];
NSLog(#"Photo Information: %#",photo_information);
NSDictionary* photo = (NSDictionary*)[photo_information objectAtIndex:0];
humanReadable.text = [NSString stringWithFormat:#"loan amount is %#",[photo objectForKey:#"loan_amount"]];
}
, the app sets the correct information on the humanredable.text property. Am I using the wrong key for the first JSON ?

Firstly, thanks for publishing your Flickr API key as-is! It will be super useful for me to perform identity theft some day.
Second, another big thanks for not having read the data you got back. It starts like this:
{"photos":{"page":1, "pages":1792, "perpage":100,
^^^^^^^^^^
So the object for the key photos is a dictionary, not an array, thus,
NSArray* photo_information = [flickr_json objectForKey:#"photos"];
is wrong. Did you mean this instead:
NSArray* photo_information = [[flickr_json objectForKey:#"photos"]
objectForKey:#"photo"];
? Also, below when you construct the human readable description,
[photo objectForKey:#"Owner"]
is wrong, it should be
[photo objectForKey:#"owner"]
instead.

Related

How to solve json Error in ios 7?

Am using following code.
+(void)getQuarterList:(NSString *)user_id
{
if ([self checkInternet])
{
NSString *url=[NSString stringWithFormat:#"%#/api/v1/quarters.json",MainURL];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"id":user_id};
// NSDictionary *parameters = #{};
// NSDictionary *parameters = #{#"id":user_id,#"auth_token":auth_token};
[manager POST:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *dict=[[NSDictionary alloc]initWithDictionary:responseObject];
//NSMutableArray *dict=[[NSMutableArray alloc]initWithArray:responseObject];
NSLog(#"dict%#",dict);
if ([dict valueForKey:#"Success"])
{
NSNotification *notif1 = [NSNotification notificationWithName:#"quarterDetailsNotifier" object:[dict valueForKey:#"Success"]];
[[NSNotificationCenter defaultCenter] postNotification:notif1];
}
else if ([dict valueForKey:#"noData"])
{
NSNotification *notif1 = [NSNotification notificationWithName:#"noDateNotifier" object:[dict valueForKey:#"Error"]];
[[NSNotificationCenter defaultCenter] postNotification:notif1];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
NSNotification *notif1 = [NSNotification notificationWithName:#"quarterDetailsFailNotifier" object:error];
[[NSNotificationCenter defaultCenter] postNotification:notif1];
}];
}
else
{
NSNotification *notif1 = [NSNotification notificationWithName:#"internetFailNotifier" object:nil];
[[NSNotificationCenter defaultCenter] postNotification:notif1];
}
}
am having following error
2014-05-20 15:39:33.610 TMLP[2770:a0b] The internet is working via WIFI.
2014-05-20 15:39:35.733 TMLP[2770:a0b] Error: 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.) UserInfo=0x8e4a1a0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set., NSUnderlyingError=0x8e65ca0 "Request failed: not found (404)"}
2014-05-20 15:39:35.734 TMLP[2770:a0b] -[NSError length]: unrecognized selector sent to instance 0x8e4a180
2014-05-20 15:39:35.737 TMLP[2770:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSError length]: unrecognized selector sent to instance 0x8e4a180'
* First throw call stack:
how to solve this error
You post error as an object of NSNotification. And in notifcation handler you use it as NSString or other object that has method length.
First things first.
Your obtained JSON text should always start with a "[" or "{" for the parser to recognise it. And the reason you are getting this error is clearly because this is not fulfilled.
I suggest you check your JSON text through a JSON validator which is available online.
And the Second thing I Suggest is to use for JSON Serialization/Deserialization is
NSJSONSerialization
And Example would be like this :
NSDictionary *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error: &error];
The options:NSJSONReadingAllowFragments might solve your problem of parsing fragments that you are getting right now. If this doesn't help, another option would be to extract out the proper JSON string from the obtained fragmented string.This means eliminating the extra unwanted characters from the starting and end of the string.
An Example would be like this :
NSURL *url=[NSURL URLWithString:#"yourURL"];
NSData *response = [NSData dataWithContentsOfURL:url];
NSString *badjsonData = [NSString stringWithUTF8String:[response bytes]];
NSString *goodJsonData = [badjsonData substringFromIndex:76];
NSString *finaljsonData = [goodjsonData substringToIndex:[goodjsonData length]-9];
NSData *goodData = [finaljsonData dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *jsonArray = [NSJSONSerialization JSONObjectWithData:goodData options:NSJSONReadingAllowFragments error: &error];

How to get value from Nsstring in ios?

I am beginner in ios and in one of my activity : this is my nsstring and now I want to get "LocationId" from this string but I have problem .....I try to add this string in array and after that get LocationId but that I have also error ....
Nsstring *Str={"UserName":"ankitdemo","UserId":"08f11980-9920-4127-8fe7-78e1c40f6002","RoleName":"Doctor","RoleId":"87b4193c-1252-4505-a81b-2b49b8db57f3","FirstName":"Ankit","MiddleName":"","LastName":"Gupta","LocationId":"5f15648f-12ef-4534-a145-4044bc7c742e"}
Nsstring *LocationId=[NSString stringWithFormat:#"%#",[Str valueForKey:#"LocationId"]];
OR
NSMutableArray *location =[[NSMutableArray alloc]init];
[location addObject:self.WebService.ptr];
NSLog(#"location id is %#",location);
LocationId=[NSString stringWithFormat:#"%#",[[location objectAtIndex:0]valueForKey:#"LocationId"]];
NSLog(#"location id is %#",LocationId);
but I have error ....
ERROR
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x881d6d0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key LocationId.'
Solve this problem.......
Do like this
You have to use JSON Parser...
NSDictionary *location = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error: &e];
NSLog(#"location id is %#",location);
LocationId=[NSString stringWithFormat:#"%#",[[location objectAtIndex:0]valueForKey:#"LocationId"]];
NSLog(#"location id is %#",LocationId);
The code you have provided has many problems and I doubt that you have copied and pasted it correctly. e.g Nsstring will not compile.
However, in general terms, you've created a string from something like a JSON dictionary, but the syntax is incorrect. And you are trying to get the value of a property that is not defined on NSString, which is the cause of your error.
You're looking for something like this:
NSDictionary *dictionary = #{ #"UserName" : #"ankitdemo",
#"UserId" : #"08f11980-9920-4127-8fe7-78e1c40f6002",
#"RoleName" : #"Doctor",#
#"RoleId" : #"87b4193c-1252-4505-a81b-2b49b8db57f3",
#"FirstName" : #"Ankit",
#"MiddleName" :#"",
#"LastName" : #"Gupta",
#"LocationId" : #"5f15648f-12ef-4534-a145-4044bc7c742e" };
NSString *locationId = dictionary[#"LocationId"];
Of course you get NSUnknownKeyException. NSString does not have LocationId accessor.
If you want to parse JSON, use JSON parsers, for example, NSJSONSerialization.
Oh, and don't use valueForKey: when you mean objectForKey:.
The code you provided won't compile, but I guess that you got some JSON as a NSString:
NSError *e;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error: &e];
if (!json)
NSLog(#"Error: %#",e);
else
NSString *locationID = [json objectForKey:#"LocationId"];

JSONKit invalid arguement when try to copy

I am parsing JSON data with JSONKit as NSMutableDictionary.
NSString *str = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
NSMutableDictionary *jsonResponse = [self.responseData objectFromJSONData];
NSMutableDictionary *newData = [[NSMutableDictionary alloc] init];
[newData addEntriesFromDictionary:[jsonResponse mutableCopy]];
When i do this i am getting this error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSMutableDictionary addEntriesFromDictionary:]: dictionary argument is not an NSDictionary'
I am trying to figure out what is causing this problem. I know that jsonResponse is an object of JKArray from my other experience.
I need help.
Thanks.
Try the following:
id object = [self.responseData objectFromJSONData];
NSLog(#"%#", [object class]);
Most likely your response is an array instead of a dictionary.
If you really want to convert the array into a dictionary, you could do something like this, using a self-defined key:
NSArray *array = [self.responseData objectFromJSONData];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject:array forKey:#"posts"];
Though perhaps there are some better options if you could show me the contents of your array.

Error with NSJSONSerialization - Invalid type in JSON write (Menu)

I have an App using core data with 3 entities with very similar attributes. The relationship is such as:
Branch ->> Menu ->> Category ->> FoodItem
Each entity has an associated class: example
I am trying to generate JSON representation of the data in sqlite database.
//gets a single menu record which has some categories and each of these have some food items
id obj = [NSArray arrayWithObject:[[DataStore singleton] getHomeMenu]];
NSError *err;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj options:NSJSONWritingPrettyPrinted error:&err];
NSLog(#"JSON = %#", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
But instead of JSON, i get a SIGABRT error.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Menu)'
Any ideas how to fix it or how to make the entity classes (Branch, Menu etc) JSON serialization compatible?
That's because your "Menu" class is not serializable in JSON. Bascially the language doesn't know how your object should be represented in JSON (which fields to include, how to represent references to other objects...)
From the NSJSONSerialization Class Reference
An object that may be converted to JSON must have the following
properties:
The top level object is an NSArray or NSDictionary.
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
All dictionary keys are instances of NSString.
Numbers are not NaN or infinity.
This means that the language knows how to serialize dictionaries. So a simple way to get a JSON representation from your menu is to provide a Dictionary representation of your Menu instances, which you will then serialize into JSON:
- (NSDictionary *)dictionaryFromMenu:(Menu)menu {
[NSDictionary dictionaryWithObjectsAndKeys:[menu.dateUpdated description],#"dateUpdated",
menu.categoryId, #"categoryId",
//... add all the Menu properties you want to include here
nil];
}
And you could will use it like this :
NSDictionary *menuDictionary = [self dictionaryFromMenu:[[DataStore singleton] getHomeMenu]];
NSError *err;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:menuDictionary options:NSJSONWritingPrettyPrinted error:&err];
NSLog(#"JSON = %#", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
There is a class method isValidJSONObject on NSJSONSerialization that tells you if a object can be serialised. As Julien pointed out you probably have to convert your object to a NSDictionary. NSManagedModel provides some handy methods to get all your attributes for your entity. So you could create a category for NSManagedObject that has a method to convert it over to a NSDictionary. This way you don't have to write a toDictionary method for each entity you want to convert to a dictionary.
#implementation NSManagedObject (JSON)
- (NSDictionary *)toDictionary
{
NSArray *attributes = [[self.entity attributesByName] allKeys];
NSDictionary *dict = [self dictionaryWithValuesForKeys:attributes];
return dict;
}
You can use + isValidJSONObject: method of NSJSONSerialization class. If it is not valid, you can use - initWithData:encoding: method of NSString.
- (NSString *)prettyPrintedJson:(id)jsonObject
{
NSData *jsonData;
if ([NSJSONSerialization isValidJSONObject:jsonObject]) {
NSError *error;
jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject
options:NSJSONWritingPrettyPrinted
error:&error];
if (error) {
return nil;
}
} else {
jsonData = jsonObject;
}
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
I had the key switched with the value : #{value :#"key"}
It should be #{#"key":value}

Data from TouchJSON getting deallocated

I have an NSArray stored as a property of my class with a retain attribute. I use a NSURLConnection to return me data as JSON. I use TouchJSON to convert it into a NSDictionary object which I store into the array. I'm using this array as the datasource for a UITableView, but after scrolling through the table a few times I get a message sent to deallocated object error.
I get the error even if I retain receivedData and searchResults.
What am I doing wrong? Thanks!
#property(retain) NSArray *myArray;
(void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Once we get response, parse it
NSError *error;
NSData *receivedData = [connectionInfo objectForKey:#"receivedData"];
NSDictionary *searchResults = [[CJSONDeserializer deserializer] deserializeAsDictionary:receivedData error:&error];
self.myArray = [searchResults objectForKey:#"myData"];
}
-[CFDictionary objectForKey:]: message sent to deallocated instance 0x14a0b70
More details: myArray is an array of dictionaries and the error occurs when I call
NSDictionary *myDict = [self.myArray objectAtIndex:indexPath.row];
[myDict objectForKey:#"id"];