I'm having a hard time managing to pull anything out of a JSON response when querying TMDb. Despite spending most of the weekend searching these forums and others, I am no nearer a solution.
In my header file I have:
#property (nonatomic,strong) NSDictionary * fetchedData;
The dictionary is populating correctly, since the first part of the JSON response looks like this when I use:
NSLog(#"fetchedData: %#", fetchedData);
fetchedData: {
page = 1;
results = (
{
adult = 0;
id = 1245;
"known_for" = (
{
adult = 0;
"backdroppath" = "/hbn46fQaRmlpBuUrEiFqv0GDL6Y.jpg";
"genreids" = ( 878, 28, 12 );
id = 24428;
"mediatype" = movie;
"original_language" = en;
"original_title" = "The Avengers";
I've been trying numerous ways to retrieve all instances of "original_title" (or any of the keys) in the response, but I have no hair left to pull out when every attempt is returning NULL, so any suggestions are welcome!
Try this.
NSString *title = fetchedData[#"results"][0][#"known_for"][0][#"original_title"];
Getting data from Response
I think fetchedData is dictionary.So
NSString *strOriginalTitle = [NSString stringWithFormat:#"%#",[[[[[fetchedData valueForKey:#"results"]objectAtIndex:0]valueForKey:#"known_for"]objectAtIndex:0]valueForKey:#"original_title"];
//OR By getting data step by step
NSArray *arrayResults = [fetchedData valueForKey:#"results"];
NSDictionary *dict = [[arrayResults objectAtIndex:0] copy];
NSArray *arrayKnownFor = [dict valueForKey#"known_for"] copy];
NSString *strOriginalTitle = [arrayKnownFor objectAtIndex:0]valueForKey:#"original_title"];
NSLog(#"The original_title is - %#",strOriginalTitle);
Related
Database (
{
to = (NSString *)
from = (NSString *)
subject = (NSString *)
uid = int
body = (NSString *)
}, { ...
)
Downloaded (
{
to = (NSString *)
from = (NSString *)
subject = (NSString *)
uid = int
body = (null)
}, { ...
)
I immediately pull and load an NSArray of about 200 NSDictionay objects from my Database into my UITableView, then I download an NSArray of the same structured NSDictionary but without a body.
Q: How do I go through all 200 Downloaded NSDictionary to see if it isn't already in my Database NSArray by matching the key: "uid"?
This should do the trick:
NSArray *arrayOfNew = [arrayDownload filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"NOT (uid IN %#)", [arrayDataBase valueForKey:#"uid"]];
Tested with this sample data, if someone want to test it:
NSDictionary *dictionary0 = #{#"to":#"0",#"from":#"0",#"uid":#(0), #"body":#"0"};
NSDictionary *dictionary1 = #{#"to":#"1",#"from":#"1",#"uid":#(1), #"body":#"0"};
NSDictionary *dictionary2 = #{#"to":#"2",#"from":#"2",#"uid":#(2), #"body":#"0"};
NSDictionary *dictionary3 = #{#"to":#"3",#"from":#"3",#"uid":#(3), #"body":#"0"};
NSDictionary *dictionary4 = #{#"to":#"4",#"from":#"4",#"uid":#(2)};
NSDictionary *dictionary5 = #{#"to":#"5",#"from":#"5",#"uid":#(5)};
NSArray *arrayDataBase = #[dictionary0, dictionary1, dictionary2, dictionary3];
NSArray *arrayDownload = #[dictionary4, dictionary5];
//So the dictionary4 shouldn't be kept, and dictionary5 should be kept.
NSArray *arrayNew = [arrayDownload filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"NOT (uid IN %#)", [arrayDataBase valueForKey:#"uid"]]];
NSLog(#"arrayNew: %#", arrayNew);
Output:
arrayNew: (
{
from = 5;
to = 5;
uid = 5;
}
With this code you can iterate in two arrays called "Downloaded" and "Database" and check if their uid match. I'm not sure if you're looking for a more elegant solution.
for (NSDictionary *dictDownloaded in Downloaded) {
for (NSDictionary *dictDatabase in Database) {
if ([dictDownloaded objectForKey:#"uid"] == [dictDatabase objectForKey:#"uid"]) {
NSLog(#"Object with uid: %d is in database", [[dictDownloaded objectForKey:#"uid"] intValue]);
}
}
}
Beware of nested loops :)
If you use Arturo's example (which works!) and download 1000 messages, you will have a potential of O(n*m) = 1000*200 = 200.000 "calculation steps"
Larme's attempt is pretty elegant (I like predicates!) but it's hard to predict the time it will use for execution, because it's all encapsulated within NSPredicate.
So another attempt, based on Larme's example data, would be to use a dictionary with the uid as the key for fast lookup.
NSMutableDictionary *databaseLookupDictionary = [[NSMutableDictionary alloc]init];
databaseLookupDictionary[#(0)] = #{#"to":#"0",#"from":#"0",#"uid":#(0), #"body":#"0"};
databaseLookupDictionary[#(1)] = #{#"to":#"1",#"from":#"1",#"uid":#(1), #"body":#"0"};
databaseLookupDictionary[#(2)] = #{#"to":#"2",#"from":#"2",#"uid":#(2), #"body":#"0"};
databaseLookupDictionary[#(3)] = #{#"to":#"3",#"from":#"3",#"uid":#(3), #"body":#"0"};
/* your download code */
// example data
NSMutableArray *downloadedData = [[NSMutableArray alloc]init];
[downloadedData addObject: #{#"to":#"0",#"from":#"0",#"uid":#(3)}];
[downloadedData addObject: #{#"to":#"0",#"from":#"0",#"uid":#(4)}];
for(NSDictionary *downloadDataDict in downloadedData)
{
// will be executed for message #4
if(![databaseLookupDictionary.allKeys containsObject:downloadDataDict[#"uid"]])
{
NSLog(#"Unknown message data found: %#", downloadDataDict);
}
}
This runs in linear time (O(n)*O(1)) so you should be fine with the performance. But keep in mind: if your message database count grows, you should think about searching directly in CoreData.
list = ({
clouds = 24;
speed = "4.31";
temp = {
day = "283.84";
eve = "283.84";
night = "283.84";
};
}),
Please can anyone tell me what am I doing wrong - I want to display list-->temp-->day value in table first I am trying to get data in an array which is terminating.
Here is my code am I doing any wrong
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:dataBuffer options:-1 error:nil];
NSLog(#"%#",json);
NSMutableDictionary * list = [json objectForKey:#"list"];
NSMutableArray *arrays = [[NSMutableArray alloc]initWithCapacity:0];
for (NSDictionary *lists in [list allValues]) {
[arrays addObject:[list valueForKey:#"temp"]];
}
If you want to access day then use below line,
NSString *day = [json valueForKeyPath:#"list.temp.day"];
Your list is an array, so if you want to do your things without changing much, you can replace:
NSMutableDictionary * list = [json objectForKey:#"list"];
With:
NSMutableDictionary * list = [[json objectForKey:#"list"] objectAtIndex:0];
This question already has answers here:
NSDictionary with ordered keys
(9 answers)
Closed 8 years ago.
I saw many examples on SO but I'm not sure if it applies to this situation. Everywhere it says NSMutableDictionries are not guaranteed an order...but I'm getting my data from the server...so my NSMuteDic looks like this:
{
joe = (
{
fromName = joe;
id = 25;
theMessage = "this is going to be a really big message...";
timeAdded = "2014-04-07 21:08:12";
toName = "me";
},
{
fromName = joe;
id = 10;
theMessage = "why???";
timeAdded = "2014-04-05 20:10:04";
toName = "me";
}
);
bob = (
{
fromName = "me";
id = 24;
theMessage = "blah blah";
timeAdded = "2014-04-06 21:15:06";
toName = bob;
},
{
fromName = bob;
id = 22;
theMessage = message;
timeAdded = "2014-04-06 20:11:57";
toName = "me";
}
);
//more entries here
}
What I want to do is change the order...put bob first and joe second. Is this really impossible to do? I saw many very complex solutions...there's no easy way to do this with just a for loop?
cellForRowAtIndexPath:
NSMutableArray *temp = [myDict objectForKey:keys[indexPath.row]];
cell.Message.text = [[reverse lastObject] valueForKey:#"theMessage"];
cell.dateTime.text = [[reverse lastObject] valueForKey:#"timeAdded"];
return cell;
This is how I'm using it...and when a row is selected I pass the array to the next view controller. The reason why I want to reorder is if a new message will be inserted in the pushed view controller, I want that dictionary to be first in the list so the root view controller can be reordered.
NSArray *keys = [myDict allKeys];
[myDict removeObjectForKey:to];
NSMutableDictionary *temp = [NSMutableDictionary dictionaryWithCapacity:[myDict.count];
temp = myDict;
[myDict removeAllObjects];
[myDict setObject:currentDict forKey:to];
for (int i=0; i<temp.count; i++) {
[myDict setObject:[temp valueForKey:keys[i]] forKey:keys[i]];
}
That's not working because it looks like since myDict is a NSObject, temp gets changed every time myDict changes...from the looks of it the logic should work but it isn't...
NSMutableDictionary is not ordered. There is nothing you can do to guarantee the order of keys because NSDictionary makes no attempt to preserve any particular ordering. To go over a dictionary in a particular order, you have to make an array of the keys that is in the order you want, then iterate that and fetch the corresponding values.
// Get the keys
NSArray *keys = [myDict allKeys];
// Sort the keys
NSArray *sortedArray = [NSArray arrayWithArray:[keys sortedArrayUsingComparator:^(NSString* a, NSString* b) {
return [a compare:b];
}]];
// Iterate the dictionary
for (NSUInteger n = 0 ; < [sortedArray count]; n++) {
id value = [myDict objectForKey:[sortedArray objectAtIndex:n]];
}
I have this data set here: https://gist.github.com/ryancoughlin/8043604 - If you see tide.tideSummary it contains an array but inside, it contains multiple dictionaries. I am trying access and display tide.tideSummary.date.pretty and display (all 33 of them) in some type of table (but that I have working with dummy data).
I was going through a somewhat similar question here: Keypath for first element in embedded NSArray
Having some trouble finding a solution to access those nested values. Been through plenty of tutorials and posts here on StackOverflow that deal with very basic JSON strings and those work great for me.
UPDATE:
Came across this question: Parsing nested JSON objects with JSON Framework for Objective-C
In my case, I have the following:
NSArray *prettyDate = [[tide objectForKey:#"tideSummary"] valueForKey:#"date"];
prettyDate prints this from NSLog
Pretty date array: (
{
epoch = 1388388109;
hour = 02;
mday = 30;
min = 21;
mon = 12;
pretty = "2:21 AM EST on December 30, 2013";
tzname = "America/New_York";
year = 2013;
},
{
epoch = 1388397506;
hour = 04;
mday = 30;
min = 58;
mon = 12;
pretty = "4:58 AM EST on December 30, 2013";
tzname = "America/New_York";
year = 2013;
},
{
epoch = 1388405656;
hour = 07;
mday = 30;
min = 14;
mon = 12;
pretty = "7:14 AM EST on December 30, 2013";
tzname = "America/New_York";
year = 2013;
}
Then I would be able to loop through each, grab the object and display?
Would I do something like:
Grab parent item tideSummary - array
Grab the item above and store date - dictionary
Access pretty via objectForKey
I have this initWithDict
-(id)initWithDict:(NSDictionary *)json {
self = [super init];
if(self) {
NSDictionary *tide = [json valueForKeyPath:#"tide"];
NSArray *arrOfTideSummaryStats = [json valueForKeyPath:#"tide.tideSummaryStats"];
NSDictionary *dctOfTideSummaryStats = [arrOfTideSummaryStats objectAtIndex:0];
NSArray *arrOfTideSummary = [json valueForKeyPath:#"tide.tideSummary"];
// Loop through the date then...
// Loop and grab 'pretty'
// The "first" is the from the example link in my question above. Experimental oonly
id pretty = [arrOfTideSummary valueForKeyPath: #"#first.tideSummary.date.pretty"];
// This all works below
self.maxheight = [NSString stringWithFormat:#"%#", [dctOfTideSummaryStats valueForKey: #"maxheight"]];
self.minheight = [NSString stringWithFormat:#"%#", [dctOfTideSummaryStats valueForKey: #"minheight"]];
/*============================================================*/
NSArray *arrOfTideInfo = [json valueForKeyPath:#"tide.tideInfo"];
NSDictionary *dctOfTideInfo = [arrOfTideInfo objectAtIndex:0];
self.tideSite = [dctOfTideInfo valueForKey:#"tideSite"];
}
return self;
}
Does anyone have any examples or a direction to steer me in? Would love a resource or question to work off of.
-(void)parseJson:(id)json{
NSDictionary *tide = [json objectForKey:#"tide"];
NSArray *tideSummary = [tide objectForKey:#"tideSummary"];
for (int i = 0; i < tideSummary.count; i++) {
NSDictionary *eachTideSummary = [tideSummary objectAtIndex:i];
NSDictionary *dateDic = [eachTideSummary objectForKey:#"date"];
NSDictionary *utcdateDic = [eachTideSummary objectForKey:#"utcdate"];
NSLog(#"Preety from date dictionary: %#", [dateDic objectForKey:#"pretty"]);
NSLog(#"Preety from utcdate dictionary: %#", [utcdateDic objectForKey:#"pretty"]);
}
}
You can take a look at Initialize NSArray with data from NSdictionary as I have already answered this
Hope this helps.
If I'm understanding what you are trying to do, you should be able to replace this part:
// Loop through the date then...
// Loop and grab 'pretty'
with something like:
for (NSDictionary *tideSummary in arrOfTideSummary) {
NSDictionary *date = [tideSummary valueForKey:#"date"];
NSLog(#"Pretty date: %#", [date valueForKey:#"pretty"]);
}
If you want the date values in a table of some sort, then you could store them into a new array or some other data structure and then create a table view that uses that as its data source.
I have below data on JSON link...
{
"results":[
{
"address_components": [
{
"long_name": "Satadhar",
"short_name": "Satadhar",
"types":[
"point_of_interest",
"establishment"
]
} ]
]
I fetched data through ASIHTTPREQUEST so the code is below given
-(void)requestFinished:(ASIHTTPRequest *)request {
NSError *err;
NSData *data=[request responseData];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&err];
arr=[[dict valueForKey:#"results"]valueForKey:#"address_components"]; //to fetch the data till inside Starting point i.e address_component
_arrTable=[[NSMutableArray alloc]init]; //take a array to store the data of the index 0 [index 0 store the whole data that is start from [array] ]
_arrTable =[arr objectAtIndex:0]; //get the data of 0th index
NSLog(#" whole data%#",_arrTable);//print it u will get the idea
NSLog(#" my %#",[[arr objectAtIndex:0] valueForKey:#"long_name"]);
NSLog(#" my %#",[[arr objectAtIndex:0] valueForKey:#"short_name"]);
[self.tblview reloadData];
}
Well I guess its an easy question (because I am only learning IOS recently).
Most of the tutorials that I have seen show simple JSON key value examples.
However I am looking a JSON structure which has the following format:
So I have lets say a JSON page that displays something like:
loans: (
{
activity = "Personal Products Sales";
"basket_amount" = 0;
"bonus_credit_eligibility" = 1;
"borrower_count" = 1;
description = {
languages = (
en
);
};
"funded_amount" = 0;
id = 623727;
image = {
id = 1457061;
"template_id" = 1;
};
"loan_amount" = 475;
location = {
country = Philippines;
"country_code" = PH;
geo = {
level = country;
pairs = "13 122";
type = point;
};
town = "Maasin City, Leyte";
};
name = Zita;
"partner_id" = 145;
"planned_expiration_date" = "2013-11-28T21:00:02Z";
"posted_date" = "2013-10-29T21:00:02Z";
sector = Retail;
status = fundraising;
use = "to buy additional stocks of soap, toothpaste, dish washing products, etc.";
},
So for example if I want to extract the name I understand the key pair ideas so I just do something like:
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* latestLoans = [json objectForKey:#"loans"]; //2
NSDictionary* loan = [latestLoans objectAtIndex:0];
NSString *name = [loan objectForKey:#"name"];
And then *name should evaluate to : Zita.
But my question is ....
1) What wizardry do I need to do in order to get access data deep inside the structure like "level = country;" (the level is located inside "geo" which is located inside "location")
Can someone explain how to do this ?
Exactly the same way as you're doing right now :)
NSDictionary* loan = [latestLoans objectAtIndex:0];
NSDictionary* location = [loan objectForKey:#"location"];
NSDictionary* geo = [locationobjectForKey:#"geo"];
NSString* level = [geo objectforKey:#"country"];
or shorter:
NSDictionary* loan = [latestLoans objectAtIndex:0];
NSString* level = loan[#"location"][#"geo"][#"level"];