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];
}
Related
When i send API i'm getting JSON response like this.
{"ABC":[{"ID1":"response","ID2":"response","ID3":"response","ID4":"response","ID5":"response"},{"ID1":"response","ID2":"response","ID3":"response","ID4":"response","ID5":"response"},{"ID1":"response","ID2":"response","ID3":"response","ID4":"response","ID5":"response"}],"status":"OK","count":3}
{"XYZ":[{"id1":"response"},{"id1":"response"},{"id1":"response"}],"status":"OK","count":3}
Here i'm getting two JSON objects in the response. How to store this data in MutableArrays.
My code is...
//Getting data from server through JSON approach ...
self.urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
self.urlReq= [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[[NSString alloc] initWithFormat:#"http://MyApiName"]]];
self.dataTask = [self.urlSession dataTaskWithRequest:self.urlReq completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!(data == nil)) {
self.loginDic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"data : %#", data);
NSLog(#"Login Dic : %#", [self.loginDic objectForKey:#"ABC"]);
if (!(self.loginDic == nil)) {
self.integer = [[self.loginDic objectForKey:#"ABC"] count];
if ([[self.loginDic objectForKey:#"status"] isEqualToString:#"OK"] && (!(self.integer == 0))) {
self.ID1 = [[NSMutableArray alloc]init];
self.ID2 = [[NSMutableArray alloc]init];
self.ID3 = [[NSMutableArray alloc]init];
self.ID4 = [[NSMutableArray alloc]init];
self.ID5 = [[NSMutableArray alloc]init];
for (int i=0; i<self.integer; i++) {
[self.ID1 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID1"]];
[self.ID2 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID2"]];
[self.ID3 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID3"]];
[self.ID4 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID4"]];
[self.ID5 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID5"]];
}
NSLog(#"%#", self.ID1);
NSLog(#"%#", self.ID2);
} else {
}
} else {
}
} else {
}
}];
[self.dataTask resume];
}
I'm getting data, but I'm getting loginDic = null.
after you get AB , its array of Dictionary
you can easily use this valueForKeyPath like:
NSArray * AB = #[#{
#"ID1":#"response",
#"ID2":#"response",
#"ID3":#"response",
#"ID4":#"response",
#"ID5":#"response",
},#{
#"ID1":#"response",
#"ID2":#"response",
#"ID3":#"response",
#"ID4":#"response",
#"ID5":#"response"
}];
NSArray * ID1 = [AB valueForKeyPath:#"ID1"];
NSArray * ID2 = [AB valueForKeyPath:#"ID2"];
How to receive two JSON objects at a time?
The JSON you show is indeed two valid JSON encodings concatenated. If your server is doing this and there is nothing you can do to fix that then you can try to fix it yourself:
Any occurrence of ][, }{, ]{ or }[ with any amount of white space between the two characters is the end of one JSON encoding and the start of the next. Construct an NSRegularExpression to find these sequences and replace them with the same close/open bracket/brace combination but with a comma (,) in between them.
Add a single [ at the start and a single ] at the end.
These two steps will converted your concatenated JSON encodings into a JSON array of the individual encodings. Now parse and process as usual remembering you first need to index into the outermost array to access the particular JSON response before your index into the response to access the elements you need.
HTH
Below is my code to access the JSON API from Edmunds.com, this works perfectly to access the information I am just having trouble with accessing the key, value pairs.
NSURL *equipmentURL = [NSURL URLWithString: [NSString stringWithFormat:#"https://api.edmunds.com/api/vehicle/v2/styles/%#/equipment?fmt=json&api_key=%#", self.carID, apiKey]];
NSData *jsonData = [NSData dataWithContentsOfURL:equipmentURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.engineArray = [NSMutableArray array];
NSArray *equipmentArray = [dataDictionary objectForKey:#"equipment"];
for (NSDictionary *carInfoDictionary in equipmentArray) {
NSArray *attributes = [carInfoDictionary objectForKey:#"attributes"];
NSLog(#"%#", attributes);
}
In the NSLog from the above code shows this:
2016-11-03 10:21:26.029 CarWise[25766:1896339] (
{
name = "Engine Immobilizer";
value = "engine immobilizer";
},
{
name = "Power Door Locks";
value = "hands-free entry";
},
{
name = "Anti Theft Alarm System";
value = "remote anti-theft alarm system";
}
)
My main question is how can I access the name and value for each array? Let's say I want to create a UILabel that will have the string of one of the values?
Probably this will help
// Array as per the post
NSArray *attributes = (NSArray *)[carInfoDictionary objectForKey:#"attributes"];
// Loop to iterate over the array of objects(Dictionary)
for (int i = 0; i < attributes.count; i++) {
NSDictionary * dataObject = [NSDictionary dictionaryWithDictionary:(NSDictionary *)attributes[i]];
// This is the value for key "Name"
NSString *nameData = [NSString stringWithString:[dataObject valueForKey:#"name"]];
NSLog(#"Value of key : (name) : %#", nameData);
}
I have below JSON Format:
{
"Get_your_story_answer": [
{
"st_id": "19",
"story_title": "Newone",
"user_fb_id": "1649424812005217",
"winner_fb_id": "1685417121693688",
"winner_fb_id2": "",
"winner_fb_id3": "",
"story": "\ud83d\ude33\ud83d\ude25\ud83d\ude14\ud83d\ude0c",
"status": "1",
"s_created_date": "2016-01-18 23:06:05",
"reply_answer": [
{
"l_id": "42",
"story_id": "19",
"user_fb_id": "1649424812005217",
"selected_user_fb_id": "1685417121693688",
"answer": "hahaha",
"l_rating": "0",
"status": "1",
"l_created_date": "2016-01-18 23:10:51",
"l_new_created_date": "2016-01-19 11:40:51",
"winner": "1",
"answer_user_id": "3",
"answer_fb_id": "1685417121693688",
"answer_user_name": "Kin Patty"
},
{
"l_id": "43",
"story_id": "19",
"user_fb_id": "1649424812005217",
"selected_user_fb_id": "1498304680499454",
"answer": "",
"l_rating": "0",
"status": "1",
"l_created_date": "2016-01-18 23:06:05",
"l_new_created_date": "2016-01-19 11:36:05",
"winner": "0",
"answer_user_id": "10",
"answer_fb_id": "1498304680499454",
"answer_user_name": "John Kingman"
}
]
}
],
"status": "1",
"msg": "Get data"
}
Now I have to get Winner id
for Example "winner_fb_id" from [Get_your_story_answer] and compare it with [reply_answer].
If [reply_answer] contain "winner_fb_id" then I have to take only that name as winner .
Like in my Example , "Kin Patty"
I have tried this ,
//_getwind is mutable array
_getwinnerid =[NSMutableArray new];
_getwinnerid=[[_dataDictionary valueForKey:#"Get_your_story_answer"]valueForKey:#"winner_fb_id"];
Here is _getwinnerid output
<__NSArrayI 0x7ffb5a57c7b0>(
1685417121693688
NSArray *replaydata=[[_dataDictionary valueForKey:#"Get_your_story_answer"]valueForKey:#"reply_answer"];
Here is Replay Data Result
if (![replaydata containsObject:_getwinnerid]) {
NSLog(#"data");
}
Note:- Winner Id will be multiple. so, I have to compare 2 or more winner id and then take name from replay data response. And then I have to set name of winner in UITableview.
The value of Get_your_story_answer is an array, the requested data is in the first item of the array
NSDictionary *getYourStoryAnswer = _dataDictionary[#"Get_your_story_answer"][0];
Now get the winner ID and the array of answers
NSString *winnerID = getYourStoryAnswer[#"winner_fb_id"];
NSArray *answers = getYourStoryAnswer[#"reply_answer"];
Then enumerate the answers array (there are other solutions using blocks etc.)
for (NSDictionary *answer in answers) {
if ([answer[#"answer_fb_id"] isEqualToString: winnerID]) {
NSLog(#"%#", answer[#"answer_user_name"]);
break;
}
}
PS: Never use valueForKey to get one value for a key from a collection type unless you really need (and mean) the KVC method. The designated method is objectForKey or key subscription like above. valueForKey applied to an array returns always an array which is normally not intended.
for this you need to get total winner count from server.
like this.
int winnerCount = 3; //[Get_your_story_answer valueForKey:#"winner_count"];
Hopefully you have a fixed pattern key for winners like winner_fb_id, winner_fb_id1, winner_fb_id2 etc.
This will give you the desired result of winners name in array.
id response; // your response here
NSArray *array = [response objectForKey:#"Get_your_story_answer"];
NSDictionary *Get_your_story_answer = array[0];
NSMutableArray *winnersArray = [[NSMutableArray alloc] init];
int winnerCount = 3; //[Get_your_story_answer valueForKey:#"winner_count"];
for (int i = 0; i< winnerCount; i++) {
NSString *winnerId = nil;
if(i != 0){
winnerId = [Get_your_story_answer valueForKey:[NSString stringWithFormat:#"winner_fb_id%d",i]];
}
else{
winnerId= [Get_your_story_answer valueForKey:[NSString stringWithFormat:#"winner_fb_id"]];
}
if(winnerId)
{
[winnersArray addObject:winnerId];
}
}
__block NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSArray *replyAnswers = [Get_your_story_answer objectForKey:#"reply_answer"];
[replyAnswers enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
NSString *answer_fb_id = [obj valueForKey:#"answer_fb_id"];
[winnersArray enumerateObjectsUsingBlock: ^(NSString * winnerId, NSUInteger idx, BOOL *stop) {
if([winnerId isEqualToString:answer_fb_id]){
// get name of winner
[resultArray addObject:[obj valueForKey:#"answer_user_name"]];
}
}];
}];
// Your name of wiiners are in resultArray.
I have filtered array using the answer as said by larme Thank you.
NSError *errorJSON = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&errorJSON];
if (!errorJSON)
{
NSDictionary *storyAnwser = [json[#"Get_your_story_answer"] firstObject];
NSArray *allAnswersKeys = [storyAnwser allKeys];
NSArray *allWinnersKeys = [allAnswersKeys filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString * _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject hasPrefix:#"winner_fb_id"];
}]];
NSLog(#"AllWinnersKeys: %#", allWinnersKeys);
NSArray *allWinnersIds = [storyAnwser objectsForKeys:allWinnersKeys notFoundMarker:[NSNull null]];
NSLog(#"AllWinnersIds: %#", allWinnersIds);
NSArray *allAnswers = storyAnwser[#"reply_answer"];
NSLog(#"AllAnswers: %#", allAnswers);
NSArray *allWinners = [allAnswers filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"answer_fb_id IN %#", allWinnersIds]];
NSLog(#"allWinners: %#", allWinners);
NSArray *allWinersNames = [allWinners valueForKey:#"answer_user_name"];
NSLog(#"AllWinnersNames: %#", allWinersNames);
}
else
{
NSLog(#"Error JSON: %#", errorJSON);
}
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.
I'm trying to get values from nsdata class and doesn't work.
here is my JSON data.
{
"count": 3,
"item": [{
"id": "1",
"latitude": "37.556811",
"longitude": "126.922015",
"imgUrl": "http://175.211.62.15/sample_res/1.jpg",
"found": false
}, {
"id": "3",
"latitude": "37.556203",
"longitude": "126.922629",
"imgUrl": "http://175.211.62.15/sample_res/3.jpg",
"found": false
}, {
"id": "2",
"latitude": "37.556985",
"longitude": "126.92286",
"imgUrl": "http://175.211.62.15/sample_res/2.jpg",
"found": false
}]
}
and here is my code
-(NSDictionary *)getDataFromItemList
{
NSData *dataBody = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
NSDictionary *iTem = [[NSDictionary alloc]init];
iTem = [NSJSONSerialization JSONObjectWithData:dataBody options:NSJSONReadingMutableContainers error:nil];
NSLog(#"id = %#",[iTem objectForKey:#"id"]);
//for Test
output = [[NSString alloc] initWithBytes:buffer length:rangeHeader.length encoding:NSUTF8StringEncoding];
NSLog(#"%#",output);
return iTem;
}
how can I access every value in the JSON? Please help me.
look like this ..
NSString *jsonString = #"your json";
NSData *JSONdata = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *jsonError = nil;
if (JSONdata != nil) {
//this you need to know json root is NSDictionary or NSArray , you smaple is NSDictionary
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:JSONdata options:0 error:&jsonError];
if (jsonError == nil) {
//every need check value is null or not , json null like ( "count": null )
if (dic == (NSDictionary *)[NSNull null]) {
return nil;
}
//every property you must know , what type is
if ([dic objectForKey:#"count"] != [NSNull null]) {
[self setCount:[[dic objectForKey:#"count"] integerValue]];
}
if ([dic objectForKey:#"item"] != [NSNull null]) {
NSArray *itemArray = [dic objectForKey:#"item"]; // check null if need
for (NSDictionary *itemDic in itemArray){
NSString *_id = [dic objectForKey:#"id"]; // check null if need
NSNumber *found = (NSNumber *)[dic objectForKey:#"found"];
//.....
//.... just Dictionary get key value
}
}
}
}
I did it by using the framework : http://stig.github.com/json-framework/
It is very powerfull and can do incredible stuff !
Here how I use it to extract an item name from an HTTP request :
(where result is the JSO string)
NSString *result = request.responseString;
jsonArray = (NSArray*)[result JSONValue]; /* Convert the response into an array */
NSDictionary *jsonDict = [jsonArray objectAtIndex:0];
/* grabs information and display them in the labels*/
name = [jsonDict objectForKey:#"wine_name"];
Hope this will be helpfull
Looking at your JSON, you are not querying the right object in the object hierarchy. The top object, which you extract correctly, is an NSDictionary. To get at the items array, and the single items, you have to do this.
NSArray *items = [iTem objectForKey:#"item"];
NSArray *filteredArray = [items filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"id = %d", 2];
if (filteredArray.count) NSDictionary *item2 = [filteredArray objectAtIndex:0];
Try JSONKit for this. Is is extremely simple to use.
Note sure if this is still relevant, but in iOS 5, apple added reasonable support for JSON. Check out this blog for a small Tutorial
There is no need to import any JSON framework. (+1 if this answer is relevant)