Extract JSON and save it in NSMutableArray - ios

Following is the my JSON, and i want to extract the data and save it to a NSMutableArray. However, this doesn't get extracted accurately. I am stuck with this for awhile now. Can someone help me out ?
Note: I want the JSON to be extracted as it is. With each sub category.
{
"Animal":[
{
"Dog":[
{
"id":"644"
}
]
},
{
"Cat":[
{
"id":"4125"
},
{
"id":"1326"
}
]
},
{
"Mouse":[
{
"id":"224"
},
{
"id":"245"
}
]
},
{
"Fish":[
{
"id":"144"
},
{
"id":"142"
}
]
}
]
}
I need to add these components to a NSMutableArray. How can i do this ?
animalArray = [[NSMutableArray alloc] init];
for (int i =0; i < [[jsonDict objectForKey:#"Animal"] count]; i++) {
dictionary= [[NSMutableDictionary alloc] init];
for (int k =0; k < [[[jsonDict objectForKey:#"Animal"] objectAtIndex:i] count]; k++) {
dictionary setObject:[[[[jsonDict objectForKey:#"Animal"] objectAtIndex:i] objectAtIndex:k] objectForKey:#"id"] forKey:#"id"];
[animalArray addObject: dictionary];
}
}

Try this to get a NSDictionary object of exact structure that of the JSON
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData // this is your JSON
options:NSJSONReadingMutableContainers
error:&jsonError];
NSLog(#"%#",json); // check the structure here

I deep recommend use Mantle Library for parse JSON content:
Mantle Lib
And here a good introduction tutorial how use this lib:
How use mantle lib
You will see how easy is parsing and use data latter , and question please fell free for ask

Related

Parsing JSON with AFNetworking

I'm trying to parse a JSON page in Objective-C by creating a subclass of NSDictionary and adding getSomeProperty methods. I have been able to do this with JSON pages that precede every [ or { with keys but am having trouble parsing the following sort of page
[ {"id":12345,"name":"name1","account_id":10002000015631,
"start_at":"2015-09-02T20:24:13","enrollments":
[{"type":"student","role":"enrollment","role_id":821,
"user_id":10000001736511,"enrollment_state":"active"}],"hide_final_grades":false,
"workflow_state":"available","restrict_enrollments_to_course_dates":false},
{"id":100000055661076,"name":"name2","account_id":100000230095635,
"start_at":"2015-08-28T21:22:41Z","grading_standard_id":null,"is_public":null,
"course_code":"name2","default_view":"wiki","enrollment_term_id":10003000007529,"end_at":null,
"public_syllabus":false,"storage_quota_mb":500,"is_public_to_auth_users":false,
"apply_assignment_group_weights":false,"calendar":{"ics":"https://someurl.ics"},
"enrollments":[{"type":"student","role":"StudentEnrollment","role_id":821,
"user_id":10000001736511,"enrollment_state":"active"}],"hide_final_grades":false,"
workflow_state":"available","restrict_enrollments_to_course_dates":false}
]
For example, for this webpage http://www.raywenderlich.com/demos/weather_sample/weather.php?format=json
I am able to create methods
- (NSDictionary *)currentCondition
{
NSDictionary *dict = self[#"data"];
NSArray *ar = dict[#"current_condition"];
return ar[0];
}
and
-(NSString*) cloudcover
{
return self[#"cloudcover"];
}
to retrieve the string #"16".
How can I use a similar method to get the #"name1" or the id #"12345" from my first example JSON code?
You have an array of dictionaries. To have an array of outputs you can use the following method:
- (NSMutableArray *)getValueString: (NSString*)string fromArray: (NSArray *)inputArray {
NSString *outputString;
NSMutableArray *outputArray = [NSMutableArray new];
for (id dict in inputArray) {
if ([[dict class] isSubclassOfClass:[NSDictionary class]]) {
outputString = [dict valueForKey: string];
}
else {
outputString = #"Name not found";
}
if (!(outputString.length > 0)) {
outputString = #"Name not found";
}
[outputArray addObject: outputString];
}
return outputArray;
}
And use it to get name with:
NSArray *resultArray = [self getValueString: #"name" fromArray: inputArray];
NSString *firstName = resultArray[0];
And to get id with:
NSArray *resultArray = [self getValueString: #"id" fromArray: inputArray];
NSString *firstId = resultArray[0];
The [ ] at the beginning and end of your JSON string indicate that it is an array, so when you parse the JSON, you will get an NSArray*, not an NSDictionary*. The first element of the array is an object, so that will be an NSDictionary*. Access id like this:
NSNumber* id = self[0][#"id"];
It looks like your currentCondition is a category on NSDictionary. If that's true and you want the above code to work, you need to make it on a category of NSArray. If it's not true, I don't understand what self is without more info.

how to search and replace in NSDictionary?

I have a JSON that I converted into NSDictionary and now I want to search and replace some values in it but I have no idea how to to this,
{
"CODE":200,
"APICODERESULT":"USER_INTERESTS",
"MESSAGE":"user interests fetched successfully",
"VALUE":{
"Books":[
{
"key":"7",
"value":"Fiction",
"selected":true
},
{
"key":"8",
"value":"Romantic",
"selected":true
}
],
"Music":[
{
"key":"11",
"value":"Classical",
"selected":false
},
{
"key":"12",
"value":"Jazz",
"selected":false
},
{
"key":"10",
"value":"Pop",
"selected":false
},
{
"key":"13",
"value":"Western",
"selected":false
}
]
}
}
here I have the value for key that I want to search in the dictionary and when I found that key with the value that I have I want to replace the value for selected in the same block.
For example:-
I have value 10 for key then I want to change the value for key selected to true
so the it will look like this
{
"CODE":200,
"APICODERESULT":"USER_INTERESTS",
"MESSAGE":"user interests fetched successfully",
"VALUE":{
"Books":[
{
"key":"7",
"value":"Fiction",
"selected":true
},
{
"key":"8",
"value":"Romantic",
"selected":true
}
],
"Music":[
{
"key":"11",
"value":"Classical",
"selected":false
},
{
"key":"12",
"value":"Jazz",
"selected":false
},
{
"key":"10",
"value":"Pop",
"selected":true
},
{
"key":"13",
"value":"Western",
"selected":false
}
]
}
}
Consider your input dictionary as mainDictionary and use following code:
NSMutableDictionary *valuesDic = [mainDictionary objectForKey:#"VALUES"];
NSArray *allPossibleKeysArray = [valuesDic allKeys];
for (int j=0; j<allPossibleKeysArray.count; j++) {
NSString *keyStr = [allPossibleKeysArray objectAtIndex:j];
NSArray *array = [valuesDic objectForKey:keyStr];
for (int i=0; i<array.count; i++) {
NSMutableDictionary *dictionary = [array objectAtIndex:i];
NSString *keyString = [NSString stringWithFormat:#"%#",[dictionary objectForKey:#"key"]];
if([keyString isEqualToString:keyvalue]){
[dictionary removeObjectForKey:#"selected"];
[dictionary setObject:[NSNumber numberWithBool:true] forKey:#"selected"];
}
}
}
Hope this helps!!
You should make such changes during parsing the JSON/moving it into model. The code below is a workaround:
NSDictionary *initialJson = //Your JSON here
NSArray *allSubKeys= [initialJson[#"Value"] allKeys];
// Your mutable output.
NSMutableDictionary *mutableJson = [initialJson mutableCopy]
for(NSString *key in allSubKeys) {//Music && Books
// Create another cointainer here
for(NSArray *arr in mutableJson[#"Value][key]) {
// Create another cointainer here
for(NSDictionary *dict in arr) {//key, value, selected
for (NSString *key2 in [dict allKeys]) {
if ([key2 isEqualToString:#"selected"] && [dict[#"value"] equals:#10]) {
// Save YES here
}
else {
// Just copy element
}
// Add object to parent container
}
// Add object to parent container
}
// Add object to parent container
}
// Add object to parent container
}
Here is full solution
NSString* str=#"{\"CODE\":200,\"APICODERESULT\":\"USER_INTERESTS\",\"MESSAGE\":\"user interests fetched successfully\",\"value\":{\"Books\":[{\"key\":\"7\",\"value\":\"Fiction\",\"selected\":true},{\"key\":\"8\",\"value\":\"Romantic\",\"selected\":true}],\"Music\":[{\"key\":\"11\",\"value\":\"Classical\",\"selected\":false},{\"key\":\"12\",\"value\":\"Jazz\",\"selected\":false},{\"key\":\"10\",\"value\":\"Pop\",\"selected\":false},{\"key\":\"13\",\"value\":\"Western\",\"selected\":false}]}}";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"dictionary before updating: %#", dictionary);
// copy old dict
NSMutableDictionary* newDict=[[[NSMutableDictionary alloc]init]autorelease];
[newDict addEntriesFromDictionary:dictionary];
// get the entry to be changed
NSMutableDictionary* valueDict=[[[NSMutableDictionary alloc]init]autorelease];
[valueDict addEntriesFromDictionary:newDict[#"value"]];
NSMutableArray* musicArray=[[[NSMutableArray alloc] init] autorelease];
[musicArray addObjectsFromArray:newDict[#"value"][#"Music"]];
// get the music array and change your property
NSMutableDictionary* musicDict2=[[[NSMutableDictionary alloc] init] autorelease];
[musicDict2 addEntriesFromDictionary:[musicArray objectAtIndex:2]];
[musicDict2 setValue:[NSNumber numberWithBool:YES] forKey:#"selected"];
[musicArray replaceObjectAtIndex:2 withObject:musicDict2];
// update the value dictionary
[valueDict setObject:musicArray forKey:#"Music"];
//update the new dictionary
[newDict setObject:valueDict forKey:#"value"];
NSLog(#"dictionary after updating: %#", newDict);

Parsing JSON Object - Objective C

I'm struggling to see why this code is not working. I have many other views using different JSON services. All working normally. However, this one is simply not. I retrieve the values back from the service as I expect however when trying to loop over it (see below code) the Array is Nil. Clearly something simple I have missed but I have been looking at this issue far to long.
Abstract View of JSON service;
{
"0": {
"altitude": "14500",
"latitude": "41.41555",
"longitude": "-73.09605",
"realname": "David KGNV"
},
"1": {
"altitude": "61",
"latitude": "33.67506",
"longitude": "-117.86739",
"realname": "Mark CT"
},
"10": {
"altitude": "38161",
"latitude": "40.51570",
"longitude": "-93.25554",
"realname": "Bob CYYZ"
},
"100": {
"altitude": "33953",
"latitude": "52.35600",
"longitude": "5.30384",
"realname": "Jim LIRQ"
}
}
Abstract view of the JSON call;
*Note the NSArray *currentMapArray valueKeyPath is set to "" as I need all elements within the JSON result.
NSError *_errorJson = nil;
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
if (_errorJson != nil) {
NSLog(#"Error %#", [_errorJson localizedDescription]);
} else {
//Do something with returned array
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary *mapJson = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Loop through the JSON array
NSArray *currentMapArray = [mapJson valueForKeyPath:#""];
//set up array and json call
mapArray = [[NSMutableArray alloc]init];
for (int i = 0; i< currentMapArray.count; i++)
{
//create our object
NSString *nAltitude = [[currentMapArray objectAtIndex:i] objectForKey:#"altitude"];
NSString *nRealname = [[currentMapArray objectAtIndex:i] objectForKey:#"realname"];
NSString *nLatitude = [[currentMapArray objectAtIndex:i] objectForKey:#"latitude"];
NSString *nLongitude = [[currentMapArray objectAtIndex:i] objectForKey:#"longitude"];
[mapArray addObject:[[LiveVatsimMap alloc]initWithaltitude:nAltitude andrealname:nRealname andlatitude:nLatitude andlongitude:nLongitude]];
}
The results of currentMapArray is NIL resulting the NSString not being filled out appropriately.
for (int i = 0; i< currentMapArray.count; i++)
Of course when I hard code the value of JSON node i.e. 10 into the ValueKeyPath then it provides the correct data results and populates accordingly.
Any ideas? Be nice...I'm only new at this objective c stuff.
Your JSON doesn't have an array - it is a dictionary of dictionaries.
You can iterate over it using
NSArray *keys=[jsonArray allKeys];
for (NSString *key in keys) {
NSDictionary *elementDictionary=jsonArray[key];
NSString *nAltitude = elementDictionary[#"altitude"];
NSString *nRealname = elementDictionary[#"realname"];
NSString *nLatitude = elementDictionary[#"latitude"];
NSString *nLongitude = elementDictionary[#"longitude"];
[mapArray addObject:[[LiveVatsimMap alloc]initWithaltitude:nAltitude andrealname:nRealname andlatitude:nLatitude andlongitude:nLongitude]];
}

Parsing values from NSArray based on JSON format

I have a NSArray which is based on JSON format. I requested it from the web and saved it in the array. I am trying to use a dictionary to get the values of "categoryname" and "subscore" and store them in new arrays, but they remain empty. Do I have to convert the array back to NSData using JSON serialisation or is there a more direct way to achieve this?
NSArray detailedscore:
{
"articles": [
{
"abstract": "text",
"title": "title"
}
],
"subscore": 3,
"categoryname": "Reporting"
},
{
"articles": [
{
"abstract": "text2",
"title": "title"
}
],
"subscore": 1,
"categoryname": "Power"
}]
}
Code:
for(int i = 0; i < [self.detailedscore count]; i++)
{
NSMutableDictionary * dc = [self.detailedscore objectAtIndex:i];
NSString * score = [dc objectForKey:#"subscore"];
NSString * categoryname = [dc objectForKey:#"categoryname"];
[self.allscores addObject:subscore];
[self.allcategories addObject:categoryname];
for (NSString *yourVar in allcategories) {
NSLog (#"Your Array elements are = %#", yourVar);
}
{} ----> means dictionary, []---> array..... this is a rule I follow while assinging the return value from webservices as NSArray or NSDictionary....
Depending on your current JSON format, perhaps this might give you an idea
NSMutableArray *categoryArray = [NSMutableArray new];
for (NSDictionary *childDict in self.detailedscore)
{
[categoryArray addObject:[childDict objectForkey:#"categoryname"]];
}
If you have the array use below code
for(int i = 0; i < [self.detailedscore count]; i++)
{
NSMutableDictionary * dc = [self.detailedscore objectAtIndex:i];
NSString * score = [dc objectForKey:#"subscore"];
NSString * categoryname = [dc objectForKey:#"categoryname"];
[self.allscores score];
[self.allcategories addObject:categoryname];
for (NSString *yourVar in allcategories) {
NSLog (#"Your Array elements are = %#", yourVar);
}
The problem wasn't in the array or dictionary or the web request. I didn't allocated the NSMutableArrays so they were empty all the time. The code works fine for extracting values from the array in case anyone wants to use it.
Hope this helps.
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) {
NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&connectionError];
NSLog(#"Dict %#",dict);
BOOL isValid = [NSJSONSerialization isValidJSONObject:dict];
if (isValid) {
[target getJSONFromresponseDictionary:dict forConnection:strTag error:connectionError];
}
else{
NSString *strResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[target getStringFromresponseDictionary:strResponse forConnection:strTag error:error];
}

Parsing JSON information in Objective C (multiple levels)

I'm able to parse a part of my JSON file but if I want to go deeper in the structure, I'm lost. Here's my JSON :
{
"album":[
{
"album_titre":"Publicité",
"album_photo":"blabla.jpg",
"album_videos":[
{
"titre_video":"Chauffage Compris",
"duree_video":"01'25''",
"photo_video":"chauffage.jpg",
"lien_video":"www.bkjas.jhas.kajs"
},
{
"titre_video":"NIFFF 2012",
"duree_video":"01'43''",
"photo_video":"nifff.jpg",
"lien_video":"www.bkjas.jhas.kajs"
}
]
},
{
"album_titre":"Events",
"album_photo":"bloublou.jpg",
"album_videos":[
{
"titre_video":"Auvernier Jazz",
"duree_video":"01'15''",
"photo_video":"auvernier.jpg",
"lien_video":"www.bkjas.jhas.kajs"
},
{
"titre_video":"NIFFF 2011",
"duree_video":"01'03''",
"photo_video":"nifff2011.jpg",
"lien_video":"www.bkjas.jhas.kajs"
}
]
},
{
"album_titre":"Culture",
"album_photo":"bilibl.jpg"
},
{
"album_titre":"Postproduction",
"album_photo":"bizoubzou"
}
]
}
And here's my objective-c code :
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary *document = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
if (document==nil)
{
NSLog( #"oops\n%#", error);
}
NSArray *album = document[#"album"];
for( NSDictionary *albumDictionary in album )
{
[album_titre addObject:albumDictionary[#"album_titre"]];
[album_photo addObject:albumDictionary[#"album_photo"]];
for( NSDictionary *album_videosDictionary in albumDictionary[#"album_videos"])
{
[titre_video addObject:album_videosDictionary[#"titre_video"]];
[duree_video addObject:album_videosDictionary[#"duree_video"]];
[photo_video addObject:album_videosDictionary[#"photo_video"]];
[lien_video addObject:album_videosDictionary[#"lien_video"]];
}
}
[self.tableView reloadData];
}
What I can't achieve is to create an array with for example contains all "titre_video" corresponding to "album_titre":"publicité". So it should contain "Chauffage Compris" and "Nifff 2012".
I know it's a kind of easy question but I've search for a while and still not able to do it.
Thank's a lot.
Nicolas
The key is to understand JSON structure:
{ } - - this means the underlying object is a dictionary.
[ ] -- this means the underlyingobject is an array
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary *document = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
// all titre:video for album_titre:publicite
NSArray *albumArray = [document objectForKey:#"album"];
NSDictionary *dict = [albumArray objectAtindex:0];
NSArray *videos = [dict objectForKey:#"album_videos"];
// to fetch Videos inside album_videos
// here you will get al the videos inside key titre_video
NSMutableArray *titreVideoArray = [[NSMutableArray alloc]init];
for(int i=0; i< videos.count; i++){
NSDictionary *dict = [videos objectAtindex:i];
NSArray *titreVideos = [dict objectForKey:#"titre_video"];
[titreVideoArray addObject: titreVideos];
}
}
It seems you want to fetch all the videos relating to different "album_titre".
I would suggest you to use NSPredicate .
NSArray *videos = [self videosArrayForTitle:#"Publicité" albumArray:albumArray];
Here we pass title and the albumArray from above to fetch us the videos array.
- (NSArray *)videosArrayForTitle:(NSString *)title albumArray:(NSArray *)albumArray{
NSPredicate *resultPredicate=[NSPredicate predicateWithFormat:#"SUBQUERY(album_titre, $content, $content CONTAINS %#).#count > 0", title];
NSArray *searchResults=[albumArray filteredArrayUsingPredicate:resultPredicate];
NSArray *videos = [searchResults objectForKey:#"album_videos"];
return videos;
}
{ } denotes NSDictionary
[ ] denotes NSArray
Copy your json into a text edit file and go in deep. You can use NSLog() to print the data, when you go deep.
Hope it will help you.

Resources