I have designed an app, which would have a button and three labels.
When the button is pressed, an URL is called. The JSON representation of the URL is as follow:
[
{
"_id": "50c87e8a1898044ea1458e4c",
"value": "10",
"time": "12:10",
"date": "12.12.12"
},
{
"_id": "50c87f311898044ea1458e4d",
"value": "12",
"time": "13:15",
"date": "12.12.12"
}
]
I also have three label in my app, that would display the value, time and date.
The code for my app is as follow:
-(IBAction)getrequest:(id)sender
{
NSURL *url =[NSURL URLWithString:#"http://localhost:3000/lights"];
NSData* data = [NSData dataWithContentsOfURL:url];
//fetch the data to the JSON Foundation opject.
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
}
- (void)fetchedData:(NSData *)responseData {
NSError *e = nil;
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
NSLog(#"%#", json);
[self processData:json];
}
-(void)processData:(NSDictionary *) JSONObject{
NSString *value = [JSONObject valueForKey:#"value"];
NSString *date = [JSONObject valueForKey:#"date"];
NSString *time = [JSONObject valueForKey:#"time"];
NSLog(#"value: %#", value);
NSLog(#"date: %#", date);
NSLog(#"time: %#", time);
_value.text = value;
_date.text = date;
_time.text = time;
}
The code compiles and builds without any error, but when I press the button in my simulator I get an exception as follow:
2012-12-12 14:16:21.115 Sensor_visulization[7956:11303] value: (
10,
12
)
2012-12-12 14:16:21.116 Sensor_visulization[7956:11303] date: (
"12.12.12",
"12.12.12"
)
2012-12-12 14:16:21.116 Sensor_visulization[7956:11303] time: (
"12:10",
"13:15"
)
2012-12-12 14:16:21.116 Sensor_visulization[7956:11303] -[__NSArrayI isEqualToString:]: unrecognized selector sent to instance 0x7191a30
2012-12-12 14:16:21.117 Sensor_visulization[7956:11303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI isEqualToString:]: unrecognized selector sent to instance 0x7191a30'
Is there any problem with my json parser?
Can I store all the values, time, date in an array?
and display the last item in the array on the label?
Any help would be really appreciated.
There seems to be a general confusion about what valueForKey does when your json object is an array of dictionary entries. Midhun's answer, solves it one way, by passing only one dictionary entry to processData (which was a logical solution because your original code's declaration of NSString *value clearly implied that you were expecting only one dictionary entry to be passed to it).
But, if you want to get arrays for all three dictionary keys for your array of dictionaries, you'd use your original fetchedData, and use valueForKey against the original json object to return NSArray objects. To do that, I'd suggest, a couple of slight modifications of your original code:
- (void)fetchedData:(NSData *)responseData {
NSError *e = nil;
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
NSLog(#"%#", json);
[self processData:json];
}
-(void)processData:(NSDictionary *) JSONObject{
// get the three array structures
NSArray *value = [JSONObject valueForKey:#"value"];
NSArray *date = [JSONObject valueForKey:#"date"];
NSArray *time = [JSONObject valueForKey:#"time"];
// these log statements demonstrate that value, date, and time are arrays
NSLog(#"value: %#", value);
NSLog(#"date: %#", date);
NSLog(#"time: %#", time);
// now, let's grab the last object from each to populate our controls
_value.text = [value lastObject];
_date.text = [date lastObject];
_time.text = [time lastObject];
}
By the way, in one of your comments, you made a parenthetical reference to wanting to chart these results. If that's the case, I might imagine that you need the dates and times combined, into NSDate objects. If you want them as NSDate objects, you could:
-(void)processData:(NSDictionary *) JSONObject{
// get the values
NSArray *value = [JSONObject valueForKey:#"value"];
// get the datetimes
NSMutableArray *datetimes = [NSMutableArray array];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"dd.MM.yy HH:mm";
formatter.locale = [NSLocale currentLocale];
for (NSDictionary *dictionary in JSONObject)
{
NSString *datetimeString = [NSString stringWithFormat:#"%# %#", [dictionary objectForKey:#"date"], [dictionary objectForKey:#"time"]];
NSDate *datetime = [formatter dateFromString:datetimeString];
[datetimes addObject:datetime];
}
NSLog(#"values=%#", values);
NSLog(#"datetimes=%#", datetimes);
Because your sample data features today's unique date, 12/12/12, I wasn't able to determine your date format, so I guessed you're using dd.MM.yy, but obviously use whatever date format string makes sense for your JSON data.
json is a NSMutableArray you are passing it to processData method as NSDictionary parameter.
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
Change the method call like:
[self processData:[json objectAtIndex:0]];
The above will display first element. If you need to display the last element use:
[self processData:[json objectAtIndex:[json count]-1]];
Related
I have the following code in my iOS app I had someone create. however, this section of the app breaks and crashes it.
if([[dictHomeSettings allKeys] containsObject:#"notify_url"]) {
NSString *notifyUrl = [dictHomeSettings objectForKey:#"notify_url"];
if(notifyUrl.length>0) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
// // You may want to cache this explicitly instead of reloading every time.
// NSData *notifyData = [NSData dataWithContentsOfURL:[NSURL URLWithString:notifyUrl]];
// NSError* error;
// NSDictionary* json = [NSJSONSerialization JSONObjectWithData:notifyData
// options:kNilOptions
// error:&error];
XMLDictionaryParser *xmlParser = [XMLDictionaryParser new];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:notifyUrl]];
NSDictionary *aDict = [xmlParser dictionaryWithParser:parser];
dispatch_async(dispatch_get_main_queue(), ^{
//NSLog(#"myNsArray : %#",aDict);
if([[aDict allKeys] containsObject:#"Notification"]) {
NSArray *array = [aDict objectForKey:#"Notification"];
if(array.count>0) {
[Common deletePreviousLocalNotifications];
for(NSDictionary *dictNotification in array) {
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
if([Common compareDate:[dictNotification objectForKey:#"StartTime"] isGreaterThanOrEqualDate:[dateFormatter stringFromDate:[NSDate date]]]) {
NSLog(#"adding notification : %#",dictNotification);
[Common addLocalNotificationAtDateTime:[dateFormatter dateFromString:[dictNotification objectForKey:#"StartTime"]] AlertBody:[dictNotification objectForKey:#"Message"] UserInfo:[NSDictionary dictionaryWithObjectsAndKeys:[dictNotification objectForKey:#"URL"], #"URL", nil]];
}
}
}
}
});
});
You're trying to call "objectForKey" on a NSString object. Please check whether the objects that you assume to be NSDictionary objects are actually NSDictionary object instances.
Obviously, You are trying to call objectForKey on an NSString object. As observed [dictNotification objectForKey:#"StartTime"] is a Number value but you are assuming it is a String (I am not sure on this). So you are getting an error on this call
[Common compareDate:(Number *) isGreaterThanOrEqualDate:(NSString *)];
You can set a Symbolic breakpoint with this symbol on -[NSObject doesNotRecognizeSelector:] to easily debug the code.
I want to save a Json Object in a field (text) sqlite and then read it again with a select and retransform to NSDictionary or NSMutableArray to parse the key/values
This is how i save actually in the sqlite DB
As you see, is a song object from the iTunes api. I want to read that object and parse it.
This is how i make the select query and save it in a NSDictionary while i filling and NSMutableArary
globals.arrayMyPlaylists = [[NSMutableArray alloc] init];
// Form the query.
NSString *query = #"select * from myplaylists";
// Get the results.
NSArray *listas = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
for (int i = 0; i < listas.count; i++) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSLog(#"lista %d %# %#", i, listas[i][0], listas[i][1]);
[dictionary setObject:listas[i][0] forKey:#"id"];
[dictionary setObject:listas[i][1] forKey:#"nombre"];
NSString *query2 = [NSString stringWithFormat:#"select cancion from canciones where idplaylist = %#", listas[i][0]];
NSArray *canciones = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query2]];
[dictionary setObject:canciones forKey:#"canciones"];
[globals.arrayMyPlaylists addObject:dictionary];
dictionary = nil;
}
When i try to read it in the cellForRowAtIndexPath method
NSArray *canciones = [[NSArray alloc] initWithArray:[[globals.arrayMyPlaylists objectAtIndex:indexPath.row] valueForKey:#"canciones"]];
and try to get the value for the key artworkUrl100
[cell.tapa1 sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", [[canciones objectAtIndex:i] valueForKey:#"artworkUrl100"]]] placeholderImage:nil];
i get the error
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x7ff575810600> valueForUndefinedKey:]: this class is not key value coding-compliant for the key artworkUrl100.'
i understand i'm messing up in some way with dictionarys/nsmutablearrays. I need some help. Thanks!
EDIT: this is how i save the data in the DB
NSString *query = [NSString stringWithFormat:#"insert into canciones (idplaylist, cancion) values ('%#', '%#')", [[globals.arrayMyPlaylists objectAtIndex:indexPath.row] valueForKey:#"id"], self.elementoSeleccionado];
[self.dbManager executeQuery:query];
self.elementoSeleccionado is the NSMutableArray with the "cancion" object and it's saved like it's shows the first image.
EDIT 2: this is what i get trying schmidt9's answer
EDIT 3: OK, i have the json string escaped. How i have to parse now?
You should parse your output first with NSJSONSerialization:
NSString *query2 = [NSString stringWithFormat:#"select cancion from canciones where idplaylist = %#", listas[i][0]];
NSArray *canciones = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query2]];
// I suppose your array canciones should contain only one song object ...
NSError *error = nil;
id object = [NSJSONSerialization JSONObjectWithData:canciones[0] options:0 error:&error];
if(error) {
// handle error ...
}
if([object isKindOfClass:[NSDictionary class]])
{
NSDictionary *result = object;
[dictionary setObject:result forKey:#"canciones"];
}
Edit
Saving to database
2 options:
- if you get a prepared json string, save it directly to DB, but before you should escape quotes. See eg. here
- if you have NSDictionary:
- (NSString*)JSONStringWithDictionary:(NSDictionary*)dictionary prettyPrinted:(BOOL)prettyPrinted
{
NSJSONWritingOptions options = (prettyPrinted) ? NSJSONWritingPrettyPrinted : 0;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:options error:nil];
return [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
}
After that you should escape the string too.
this is the json string that i am receiving from the API:
"incentives_and_benefits" = "{\"food\":{\"0\":\"\"},\"commission\":{\"0\":\"\"},\"uniform\":{\"0\":\"\"},\"transport\":{\"0\":\"\"},\"extras\":{\"0\":\"\"}}";
and i assigned it to dictionary. Now I need to get the values inside the dictionary.
I tried using the solution given here: How to get values from dict
Heres what I have so far:
NSString *strIncentives = [[self.jobDetailDict objectForKey:#"sub_slots"] objectForKey:#"incentives_and_benefits"];
NSData *jsonData = [strIncentives dataUsingEncoding:NSUTF8StringEncoding];
NSError *e;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e];
NSLog(#"DICT: %#", dict);
NSString *food = [dict objectForKey:#"food"];
NSLog(#"DICT: %#", food);
NSString *commission = [dict objectForKey:#"commission"];
NSLog(#"DICT: %#", commission);
NSString *uniform = [dict objectForKey:#"uniform"];
NSLog(#"DICT: %#", uniform);
NSString *transport = [dict objectForKey:#"transport"];
NSLog(#"DICT: %#", transport);
NSString *extras = [dict objectForKey:#"extras"];
NSLog(#"DICT: %#", extras);
Now I need to check whether food's value is 0 or 1..When Food's value is 1 then i need to get Hello string and display it. (this is just an example) food: {"1":"Hello"}
if([food isEqualToString:#""])
{
//the string will be placed here
NSLog(#"FOOD Available")
}
when i reach the if statement i get an error:
[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance
How will i be able to resolve this?
please help and thank you in advance.
if([[dict objectForKey:#"food"]isEqualToString:#“”]){
NSLog(#"FOOD Available")
}
I was passed NSstring it is coming properly data into uitableview but when I am parsing integer value it showing exception Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: -[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x744e9d0
This is my code
(void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData options:kNilOptions error:&error];
NSArray * values=[json objectForKey:#"loans"];
NSLog(#"Array: %#",values);
for (NSDictionary *file in values)
{
NSNumber *fileTitle=[file objectForKey:#"id"];
// NSString *fileTitle = [file objectForKey:#"sector"];
[titles addObject: fileTitle];
}
[self.mainTableView reloadData];
}
You are assigning string value to NSNumber type.
Try to use this
NSString *fileTitle=[file objectForKey:#"id"];
[titles addObject: fileTitle];
and use string value.
[[titles addObject: fileTitle] stringValue];
I guess you are doing something like this in your -tableView: cellForIndexPath:
UITableViewCell *cell = [...];
cell.titleLabel.text = titles[indexPath.row];
You can only use NSString for -[UILabel setText:] method.
Convert your NSNumber to NSString with a simple -[NSNumber stringValue] or using NSNumberFormatter.
Everything seems ok. Just replace
NSNumber *fileTitle=[file objectForKey:#"id"];
by NSString *fileTitle = [file objectForKey:#"id"];
I'm newbie in iOS. And I'm having a problem accessing my JSON file that I retrieve in my web app server.
JSON:
{
"content": [
{
"info": [
{
"type": "TEL",
"label": "Call Phone",
"id": "32d7da39-39cc-4319-ab76-e67db9385722"
}
],
"name": "myname",
"title": "myname_title",
"image": "",
}
],
"timestamp": 1370491676,
"error": "SUCCESS"
}
I convert NSData to JSON :
NSMutableDictionary *mydatas =[NSJSONSerialization JSONObjectWithData:urlData options:kNilOptions error:&error];
When I'm using this code to retrieve the name:
NSString *name = [[mydatas objectForKey:#"content"] objectForKey:#"name"];
It terminate the program.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x71e3240'
Include SBJSon Framework from here
NSString *responseString = [[NSString alloc]initWithData: urlData encoding:NSUTF8StringEncoding];
//NSLog(#"%#",responseString);
NSDictionary * mydatas = [responseString JSONValue];
NSString *name = [[mydatas objectForKey:#"content"]objectForKey:#"name"];
content is an NSArray, not an NSDictionary. You need to use NSArray calls to retrieve the item in the array:
// Be sure to check that the array has at least one item or you'll throw an exception
NSArray *contentArray = [mydatas objectForKey:#"content"];
if ( contentArray.count > 0 ) {
NSString *image = [contentArray[0] objectForKey:#"name"];
}
Why you are not using the SBJSON framework . https://github.com/stig/json-framework/.
Then refer following SO question :How to parse JSON into Objective C - SBJSON . This will be easy for you to parse this data.
NSArray *contentArray = [mydatas objectForKey:#"content"];
[contentArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"name of content at index %i is == %#",idx,[obj valueForKey:#"name"]);
}];
By looking at your JSON I can say,
Your mydatas dictionary contains 3 keys which are content, timestamp, error
The object for key content is an array. If you want to retrieve the object for key name you need to do the following
if([[mydatas objectForKey:#"content"] count]>0)
{
NSString *name = [[[mydatas objectForKey:#"content"] objectAtIndex:0]objectForKey:#"name"];
}
This will work.
try like this,
NSString *name = [[[mydatas objectForKey:#"content"] objectAtIndex:0]objectForKey:#"name"];
Try This One
NSMutableDictionary *mydatas =[NSJSONSerialization JSONObjectWithData:urlData options:kNilOptions error:&error];
Save it to Array
NSArray *array = [mydatas objectForKey:#"content"];
for (int i=0; i<[array count]; i++) {
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:[[array objectAtIndex:i] valueForKey:#"info"] forKey:#"info"];
[someArray addObject:dic];
[typeArray addObject:[[dic valueForKey:#"info"] valueForKey:#"type"] valueForKey:#"name"]];
NSString * NameStr = [typeArray objectAtIndex:i];
NSLog(#"String For Name : %#",NameStr);
[dic release];
}
Hope its Work!!!!!!!!!!!