Restructure the array - iphone

I get a return array by json,
[{"date": "2011-01-01", "title": "aaa"},
{"date": "2011-01-01", "title": "bbb"},
{"date": "2011-01-01", "title": "ccc"},
{"date": "2011-01-02", "title": "ddd"},
{"date": "2011-01-02", "title": "eee"},
{"date": "2011-01-03", "title": "fff"},
{"date": "2011-01-03", "title": "ggg"}]
I use these code to get the value:
NSDictionary *jsonDictionary = [jsonArray objectAtIndex:i];
NSString *date = [jsonDictionary objectForKey:#"dispalyDate"];
NSString *title = [jsonDictionary objectForKey:#"title"];
The problem is how can I restructure the array or create new array according to the same date, such as
date = 2011-01-01
aaa、bbb、ccc
date = 2011-01-02
ddd、eee
date = 2011-01-03
fff、ggg

Something like this...
NSMutableDictionary *titlesByDate = [NSMutableDictionary dictionary];
for (NSDictionary *entry in jsonDictionary) {
NSString *date = [entry objectForKey:#"date"];
NSMutableArray *titles = [titlesByDate objectForKey:date];
if (!titles) {
titles = [NSMutableArray array];
[titlesByDate setObject:titles forKey:date];
}
[titles addObject:[entry objectForKey:#"title"]];
}
Now you have a dictionary where the keys are date strings and the values are title arrays. If you really want an array result, you can then do this:
NSMutableArray *array = [NSMutableArray array];
for (NSString *date in titlesByDate) {
[array addObject:[NSDictionary dictionaryWithObjectsAndKeys:
date, #"date",
[titlesByDate objectForKey:date], #"titles",
nil];
}

Related

JSON Arrays and Sorting

I have this json array which I have outlined below. I want to know how I could get all the strings under the "name" key only and place in a certain array to be sorted alphabetically by name and later split into further arrays in accordance to the first letter in the names. Any guide to carrying this out will be much appreciated, thanks. I am using the json kit via github and also NSJSONserialization.
{
"proj_name": "Ant",
"id":
[
{
"name": "David"
},
{
"name": "Aaron"
}
]
},
{
"proj_name": "Dax",
"id":
[
{
"name": "Adrian"
},
{
"name": "Dan"
}
]
}
Here is sample that selects just names and sort them alphabetically. Replace responseData with your data object.
NSMutableArray *names = [[NSMutableArray alloc] init];
NSError* error;
NSArray* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
for (NSDictionary *proj in json) {
NSArray *ids = [proj objectForKey: #"id"];
for (NSDictionary *name in ids)
{
[names addObject: [name objectForKey: #"name"];
}
}
NSArray *sortedNames = [names sortedArrayUsingSelector: #selector(localizedCaseInsensitiveCompare:)];
Go to http://json.bloople.net/ in this link you can see the structure of your JSON response.
from the above response i can see the response as follow:
Project name: Dax
id : 0 name : Adrian
1 name : Dan
So you can use the NSjsonserialization class from Apple. No need to use JSON kit.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"Your URL"]]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSLog(#"url=%#",request);
id jsonObject = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingAllowFragments error:nil];
if ([jsonObject respondsToSelector:#selector(objectForKey:)])
{
Nsstring *projectname=[jsonObject objectForKey:#"proj_name"];
NSArray *name_array=[jsonObject objectForKey:#"id"];
NSLog(#"projectname=%#",projectname);
NSLog(#"name_array=%#",name_array);
}
Assuming you've successfully parsed the JSON into an NSArray, you can simplify things pretty dramatically:
NSArray *names = [parsedArray valueForKeyPath:#"#distinctUnionOfArrays.id.name"];
The names array should now contain all of the names flattened into a single array. To sort them, you could then do:
NSArray *sortedNames = [names sortedArrayUsingDescriptors:#[[NSSortDescriptor
sortDescriptorWithKey:#"description" ascending:YES]]];
Or all at once:
NSArray *sortedNames = [[parsedArray valueForKeyPath:#"#distinctUnionOfArrays.id.name"]
sortedArrayUsingDescriptors:#[[NSSortDescriptor
sortDescriptorWithKey:#"description"
ascending:YES]]];
The sortedNames array would now contain:
<__NSArrayI 0x713ac20>(
Aaron,
Adrian,
Dan,
David
)

JSON how to call an object in a different list

I currently have an JSON API that looks like this:
{
"posts": [
{
"id": 277,
"title": "test title",
"content": "test content",
"attachments": [
{
"url": "http:\/\/www.example.com\/bar-icon-help#2x.png"
}
}
}
I'm trying to use the "url" which is under "attachments". Please take a look at what im doing wrong:
-(void)dataRequestCompletedWithJsonObject.(id)jsonObject
{
NSDictionary *recipeDictionary = (NSDictionary*)jsonObject;
NSArray* recipeArray = (NSArray*)[recipeDictionary objectForKey:#"posts"];
self.recipes = [[NSMutableArray alloc] init];
for (NSDictionary* dic in recipeArray) {
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [dic objectForKey:#"title"];
recipe.thumbNail = [[dic objectForKey:#"attachements"]objectForKey:#"url"];
recipe.twitterShareCount = [[dic objectForKey:#"id"] intValue];
[recipes addObject:recipe];
}
Mainly trying to figure out what i should use instead of this line:
recipe.thumbNail = [[dic objectForKey:#"attachements"]objectForKey:#"url"];
Thanks to anyone who helps!
You have an array of dicts in attachments object.
[[[dic objectForKey:#"attachements"] objectAtIndex:0] objectForKey:#"url"]

Array is remain still empty while fetching coordinates

I have array of country names and i want to get coordinates of them and store into another array. after this function my longitudes and latitudes arrays are remains still empty. do you have idea what is problem here ? i can't understand.
My Code is :
- (void)geocode {
NSString *strcountry=[[NSString alloc]init];
countryLati=[[NSMutableArray alloc]init];
countryLongi=[[NSMutableArray alloc]init];
countryName =[NSMutableArray arrayWithObjects:#"Bahrain",#"Bangladesh",#"Bhutan",#"China",#"Georgia",#"Hong Kong",nil ];
int count=[countryName count];
for(int i=0;i<count;i++)
{
strcountry=[countryName objectAtIndex:i];
[SVGeocoder geocode:strcountry
completion:^(NSArray *placemarks, NSHTTPURLResponse *urlResponse, NSError *error) {
//NSLog(#"placemarks = %#", placemarks);
CLPlacemark *place = [placemarks objectAtIndex:0];
CLLocation *location = place.location;
CLLocationCoordinate2D coord = location.coordinate;
NSString *tempLati=[[NSString alloc]initWithFormat:#"%g",coord.latitude];
NSString *tempLongi=[[NSString alloc]initWithFormat:#"%g",coord.longitude];
NSLog(#"-------------------------");
NSLog(#"Country : %#",strcountry);
NSLog(#"Latitude : %# ",tempLati);
NSLog(#"Longitude : %# ",tempLongi);
[countryLati addObject:tempLati];
[countryLongi addObject:tempLongi];
}];
}
NSLog(#"%d",[countryName count]);
NSLog(#"%d ",[countryLati count]);
NSLog(#"%d ",[countryLongi count]);
}
I accept Nuzhat Zari solution. Below is the code without using blocks and 3rd party Libraries. Its just a suggetion and showing you one more way of getting location details.
https://developers.google.com/maps/documentation/geocoding/
this URL has a good documentation for Google API.
- (void)geocode
{
NSString *strcountry=[[NSString alloc]init];
countryLati=[[NSMutableArray alloc]init];
countryLongi=[[NSMutableArray alloc]init];
countryName =[NSMutableArray arrayWithObjects:#"Bahrain",#"Bangladesh",#"Bhutan",#"China",#"Georgia",#"Hong Kong",nil ];
int count=[countryName count];
for(int i=0;i<count;i++)
{
strcountry=[countryName objectAtIndex:i];
NSString *urlString = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=csv", strCountry];
NSString* webStringURL = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:webStringURL];
NSString *locationString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(#"Location String = %#", locationString);
NSArray *receivedGoogleData = [[NSArray alloc] initWithArray:[locationString componentsSeparatedByString:#","]];
searchTermLocation = [[CLLocation alloc] initWithLatitude:[[receivedGoogleData objectAtIndex:2] doubleValue] longitude:[[receivedGoogleData objectAtIndex:3] doubleValue]];
[countryLati addObject:[[receivedGoogleData objectAtIndex:2] doubleValue]];
[countryLongi addObject:[[receivedGoogleData objectAtIndex:3] doubleValue]];
}
NSLog(#"%d",[countryName count]);
NSLog(#"%d ",[countryLati count]);
NSLog(#"%d ",[countryLongi count]);
}
#Mahesh Dhapa : Try this one, From my perspective, I feel this is easy than your way of SVGeoCoder, because no need to extra importing of SVGeocoder classes. BTW, SVGeocoder is simple. But, This is also straight forward without using 3rd party libraries.
You get response from Google like this
200,1,23.8954,34.5478
In which,
200 - Success
1 - Accuracy
23.8954 - Latitude of location
34.5478 - Longitude of location
You can also get this in JSON and XML Format with extra clear information, But you need to decode them to Dictionary from JSON and XML format to use them.
Example JSON Format :
{
"name": "Bahrain",
"Status": {
"code": 200,
"request": "geocode"
},
"Placemark": [ {
"id": "p1",
"address": "Bahrain",
"AddressDetails": {
"Accuracy" : 1,
"Country" : {
"CountryName" : "Bahrain",
"CountryNameCode" : "BH"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 26.3240565,
"south": 25.5798401,
"east": 50.8228639,
"west": 50.3781509
}
},
"Point": {
"coordinates": [ 50.5577000, 26.0667000, 0 ]
}
} ]
}
Example XML Response :
<kml xmlns="http://earth.google.com/kml/2.0">
<Response>
<name>Bahrain</name>
<Status>
<code>200</code>
<request>geocode</request>
</Status>
<Placemark id="p1">
<address>Bahrain</address>
<AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" Accuracy="1">
<Country>
<CountryNameCode>BH</CountryNameCode>
<CountryName>Bahrain</CountryName>
</Country>
</AddressDetails>
<ExtendedData>
<LatLonBox north="26.3240565" south="25.5798401" east="50.8228639" west="50.3781509"/>
</ExtendedData>
<Point>
<coordinates>50.5577000,26.0667000,0</coordinates>
</Point>
</Placemark>
</Response>
</kml>
I think when you want to change local variable in block you need to declare it as block, as follows:
NSArray *stringsArray = #[ #"string 1",
#"String 21",
#"string 12",
#"String 11",
#"Strîng 21",
#"Striñg 21",
#"String 02" ];
NSLocale *currentLocale = [NSLocale currentLocale];
__block NSUInteger orderedSameCount = 0;
NSArray *diacriticInsensitiveSortArray = [stringsArray sortedArrayUsingComparator:^(id string1, id string2) {
NSRange string1Range = NSMakeRange(0, [string1 length]);
NSComparisonResult comparisonResult = [string1 compare:string2 options:NSDiacriticInsensitiveSearch range:string1Range locale:currentLocale];
if (comparisonResult == NSOrderedSame) {
orderedSameCount++;
}
return comparisonResult;
}];
NSLog(#"diacriticInsensitiveSortArray: %#", diacriticInsensitiveSortArray);
NSLog(#"orderedSameCount: %d", orderedSameCount);
Edit:A statement from reference.
A powerful feature of blocks is that they can modify variables in the
same lexical scope. You signal that a block can modify a variable
using the __block storage type modifier.
So you should declare countryLati and countryLongi as block storage.

parsing json in iphone

I ve got a twitter json Feed.the thing is i m getting error while parsing the json feed .i m using jsonkit.below is the json url.i want to parse the value text and profile_background_image_url in the below json feed.cud u guys help me out
[
{
"created_at": "Mon Jul 09 21:46:49 +0000 2012",
"id": 222446736654872580,
"id_str": "222446736654872576",
"text": "#mevru you have to go to : http://t.co/pPGYijEX",
"source": "web",
"truncated": false,
"in_reply_to_status_id": 222445085235752960,
"in_reply_to_status_id_str": "222445085235752961",
"in_reply_to_user_id": 146917266,
"in_reply_to_user_id_str": "146917266",
"in_reply_to_screen_name": "mevru",
"user": {
"id": 145125358,
"id_str": "145125358",
"name": "Amitabh Bachchan",
"screen_name": "SrBachchan",
"location": "Mumbai, India",
"description": "Actor ... well at least some are STILL saying so !!",
"url": "http://srbachchan.tumblr.com",
"protected": false,
"followers_count": 3022511,
"friends_count": 415,
"listed_count": 22016,
"created_at": "Tue May 18 05:16:47 +0000 2010",
"favourites_count": 10,
"utc_offset": 19800,
"time_zone": "Mumbai",
"geo_enabled": false,
"verified": true,
"statuses_count": 14166,
"lang": "en",
"contributors_enabled": false,
"is_translator": false,
"profile_background_color": "BADFCD",
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/144221357/t-1.gif",
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/144221357/t-1.gif",
"profile_background_tile": true,
"profile_image_url": "http://a0.twimg.com/profile_images/2227330575/Amitji_normal.png",
"profile_image_url_https": "https://si0.twimg.com/profile_images/2227330575/Amitji_normal.png",
"profile_link_color": "FF0000",
"profile_sidebar_border_color": "F2E195",
"profile_sidebar_fill_color": "FFF7CC",
"profile_text_color": "0C3E53",
"profile_use_background_image": true,
"show_all_inline_media": true,
"default_profile": false,
"default_profile_image": false,
"following": null,
"follow_request_sent": null,
"notifications": null
}
following is the ios code that i used to parse
jsonurl=[NSURL URLWithString:#"https://api.twitter.com/1/statuses/user_timeline.json?screen_name=#SrBachchan&count=10"];
jsonData=[[NSString alloc]initWithContentsOfURL:jsonurl];
jsonArray = [jsonData objectFromJSONString];
items = [jsonArray objectForKey:#"text"];
NSLog(#"the given text:%#",items);
story = [NSMutableArray array];
title = [NSMutableArray array];
picture = [NSMutableArray array];
for (NSDictionary *item in items )
{
}
The problem is in this line:
items = [jsonArray objectForKey:#"text"];
As your code suggest it's an array not a dictionary thus you have grab the object from the array first:
for (NSDictionary *item in jsonArray ) {
NSDictionary *user = [item objectForKey:#"user"];
NSString *imageURLString = [user objectForKey:#"profile_image_url"];
}
NSData *data = [NSData dataWithContentsOfURL:jsonurl];
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if (!array) return;
NSDictionary *dictionary = [array objectAtIndex:0];
if (dictionary){
NSString *text = [dictionary valueForKey:#"text"];
NSString *profileBackgroundImageURL = [dictionary valueForKeyPath:#"user.profile_background_image_url"];
}
Use jsonlint.com to validate your JSON.
The error is lacking of the last closing operand } at the end of JSON string.
There're 2 opening but only one closing.
Parse error on line 52:
...cations": null }
----------------------^
Expecting '}', ',', ']'
Try this
items = [[jsonArray objectAtIndex:0] objectForKey:#"text"];
backImage=[[[jsonArray objectAtIndex:0] objectForKey:#"user"] objectForKey:#"profile_background_image_url"] ;

Need help using json-framework on iPhone

So I've got json-framework up and running on my project, but need help figuring out how to use it to parse this json string:
[
{
"id":"0",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
},
{
"id":"1",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
}
]
Any help and maybe sample code on how to go about this specific type of json would be great. Somehow I can't get it into a dictionary I can read out of. Thanks so much.
The reason why you can't get this string into a dictionary is because it isn't a dictionary, it's an array of dictionaries
You can get the values into an Objective-C object by storing it in an NSArray:
NSArray *objects = (NSArray*) [jsonString JSONValue];
Then, you can loop over those objects that are in the array:
for(NSDictionary *dict in objects) {
NSString *id = (NSString *) [dict objectForKey:#"id"];
NSString *name = (NSString *) [dict objectForKey:#"name"];
NSArray *tags = (NSArray *) [dict objectForKey: #"tags"];
//loop over tags here...
for(NSDictionary *tag in tags) {
NSString *tag_id = (NSString *) [tag objectForKey:#"id"];
NSString *tag_name = (NSString *) [tag objectForKey:#"tag"];
}
//...
}