Splitting JSON data in iPhone - iphone

I got this data from my server using JSON:
{
ID = 198;
dtDate = "2012-03-14 00:00:00";
dtTime = "06:00:00";
iPublished = 1;
sProgram = "Devotional Hits";
}
{
ID = 199;
dtDate = "2012-03-14 00:00:00";
dtTime = "07:00:00";
iPublished = 1;
sProgram = "Old Malayalam Hits";
}
{
ID = 200;
dtDate = "2012-03-14 00:00:00";
dtTime = "08:00:00";
iPublished = 1;
sProgram = "Malayalam New Hits";
}
{
ID = 201;
dtDate = "2012-03-14 00:00:00";
dtTime = "09:00:00";
iPublished = 1;
sProgram = "Melody Songs";
}
{
ID = 202;
dtDate = "2012-03-14 00:00:00";
dtTime = "10:00:00";
iPublished = 1;
sProgram = "Jayachandran Hits";
}
{
ID = 203;
dtDate = "2012-03-14 00:00:00";
dtTime = "11:00:00";
iPublished = 1;
sProgram = "Yesudas Hits";
}
{
ID = 204;
dtDate = "2012-03-14 00:00:00";
dtTime = "12:00:00";
iPublished = 1;
sProgram = "Ilayaraja Hits";
}
I need to split this data and store sProgram data into an array.. need help.
I need to split this format and I want sProgram and dtTime separately. What should I do for that. I'm a little bit confused about string formatting.

If you are using < IOS 5, add SBJSON to your project
//in some.m file
#import JSON.h
// Lets say NSString *recievedValue contains your JSON response.
id jsonRep = [receivedValue jsonValue];
if([jsonRep isKindOfClass:[NSArray class]])
{
// returned JSON Value has a array structure.
NSArray *value = (NSArray *)jsonRep;
//You can access values using objectAtIndex: method if you already know the Index of a value, in your case i think each array object is a NSDictionary
if([[value objectAtIndex:0] isKindOfClass:[NSDictionary class]])
{
// returned JSON Value has a key value compliant structure.
NSDictionary *dicValue = (NSDictionary *)[value objectAtIndex:0];
//You can access values using objectForKey: method if you already know the key value, in your case it can be #"sProgram" for example
}
}
else if([jsonRep isKindOfClass:[NSDictionary class]])
{
// returned JSON Value has a key value compliant structure.
NSDictionary *value = (NSDictionary *)jsonRep;
//You can access values using objectForKey: method if you already know the key value, in your case it can be #"sProgram" for example
}

Your JSON is invalid - I recommend that you use this tool to check this before posting about a JSON-related issue in the future.
However, I have corrected your JSON and validated it - it should look like this:
[
{
"ID": 198,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "06:00:00",
"iPublished": 1,
"sProgram": "Devotional Hits"
},
{
"ID": 199,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "07:00:00",
"iPublished": 1,
"sProgram": "Old Malayalam Hits"
},
{
"ID": 200,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "08:00:00",
"iPublished": 1,
"sProgram": "Malayalam New Hits"
},
{
"ID": 201,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "09:00:00",
"iPublished": 1,
"sProgram": "Melody Songs"
},
{
"ID": 202,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "10:00:00",
"iPublished": 1,
"sProgram": "Jayachandran Hits"
},
{
"ID": 203,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "11:00:00",
"iPublished": 1,
"sProgram": "Yesudas Hits"
},
{
"ID": 204,
"dtDate": "2012-03-14 00:00:00",
"dtTime": "12:00:00",
"iPublished": 1,
"sProgram": "Ilayaraja Hits"
}
]
You can then use the json-framework to parse it.
As you asked, here is how you can now obtain all the values of sProgram:
NSMutableArray *programs = [[NSMutableArray alloc] init];
NSArray *data = [json jsonValue];
for (NSDictionary *dict in data) {
[programs addObject:[dict objectForKey:#"sProgram"]];
}
// programs now contains all the values of sProgram

actually i used Stig Brautaset’s JSON library (version 2.2)
- (void)viewDidLoad
{
[super viewDidLoad];
[table reloadData];
NSMutableData *responseData;
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://ganamradio.com/smartphones/date.php"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
// Do any additional setup after loading the view from its nib.
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//label.text = [NSString stringWithFormat:#"Connection failed: %#", [error description]];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
//[responseData release];
dict=[responseString JSONValue];
NSArray *Programs;
NSArray *Time;
Programs=[dict valueForKey:#"sProgram"];
Time=[dict valueForKey:#"dtTime"];
NSLog(#"......%#",Time);
}
so i got the program list in NSArray programs,, is their any problem using like this..?

Related

Using the YouTube API and iPhone SDK, how would I get information about a search result?

I'm trying to simply search for videos using a query, which is working perfectly using the below code.
// Create a service object for executing queries
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
// Services which do not require sign-in may need an API key from the
// API Console
service.APIKey = #"AIzaSy...";
// Create a query
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id,snippet"];
query.maxResults = 10;
query.q = searchBar.text;
query.videoEmbeddable = #"true";
query.type = #"video";
//query.country = #"US";
// Execute the query
GTLServiceTicket *ticket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
// This callback block is run when the fetch completes
if (error == nil) {
GTLYouTubeSearchListResponse *products = object;
[videoArray removeAllObjects];
// iteration of items and subscript access to items.
for (GTLYouTubeSearchResult *item in products) {
NSMutableDictionary *dictionary = [item JSONValueForKey:#"id"];
NSLog(#"%#", [dictionary objectForKey:#"videoId"]);
YoutubeVideo *video = [[YoutubeVideo alloc]init];
[video setLblTitle:item.snippet.title];
//Get youtube video image
[video setImgIconURL:[NSURL URLWithString:item.snippet.thumbnails.defaultProperty.url]];
[video setLblVideoURL:[dictionary objectForKey:#"videoId"]];
[video setLblChannelTitle:item.snippet.channelTitle];
[videoArray addObject:video];
}
reloadData = YES;
[tableView reloadData];
//Download images asynchronously
[NSThread detachNewThreadSelector:#selector(downloadImages)
toTarget:self
withObject:nil];
}else{
NSLog(#"Error: %#", error.description);
}
}];
However, now I'd like to display certain information about the video. Some of this information I can get out of
item.snippet
But I also need to get the video duration, and number of views. How can I get them using Youtube API 3.0?? I also had an idea to try using GData just for this, but it literally triples the load time to use
NSString *JSONString = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://gdata.youtube.com/feeds/api/videos/%#?v=2&alt=json", [video lblVideoURL]]] encoding:NSUTF8StringEncoding error:nil ];
How do I get the duration of the video, plus the number of views the video has?
Search query only accept ID and Snippet as parts. If you change to Video List Query you can include other parts, but you have to use one of the filters.
I think you'll have to get the video ID with the search query and do another query (Now a video query) filtering by ID (the Id you got), than you can get all other information of the videos you searched.
The problem is i'm having trouble getting the video ID, i think the API use the word "identifier" instead of "id" because it's a reserved word of objective-c.
Edit: Yeah, it was just a matter of time, just request my GTLYoutubeSearchResponse.JSON, an manipulated it as i wanted.
FIRST QUERY:
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id,snippet"];
query.maxResults = 10;
query.q = #"iphone";
query.fields = #"items(id,snippet)";
query.order = #"viewCount";
//query.channelId = #"UCsnbNwitAF9BzjjdMfRyK2g";//Kavaco
[appDelegate.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error == nil) {
appDelegate.videos = object;
[self performSegueWithIdentifier:#"videoList" sender:self];
}
else {
NSLog(#"%#", error.description);
}
}];
SECOND QUERY: In my TableViewController, inside my cellForRowAtIndexPath i do another query for each video i found. Be sure to request only the variables you need to avoid spending your credits, in my case i requested only viewCount.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myCell" forIndexPath:indexPath];
GTLYouTubeVideo *video = appDelegate.videos[indexPath.row];
NSMutableDictionary *videoIdJson = [video.JSON objectForKey:#"id"];
NSString *videoId = [videoIdJson objectForKey:#"videoId"];
cell.textLabel.text = video.snippet.title;
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosListWithPart:#"statistics"];
query.identifier = videoId;
query.maxResults = 1;
query.fields = #"items/statistics(viewCount)";
[appDelegate.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error == nil) {
GTLYouTubeVideoListResponse *detalhe = object;
NSMutableDictionary *responseJSON = detalhe.JSON;
NSArray *tempArray = [responseJSON objectForKey:#"items"];
NSMutableDictionary *items = tempArray[0];
NSMutableDictionary *statistics = [items objectForKey:#"statistics"];
_views = [[NSString alloc] initWithFormat:#"Views: %#",[statistics objectForKey:#"viewCount"]];
cell.detailTextLabel.text = _views;
}
else {
NSLog(#"%#", error.description);
}
}];
cell.detailTextLabel.text = _views;
return cell;
}
Hope it helps.
Collect the id from search API and do another video list API call is the proper way to do what you want to achieve. The video list API call can put multiple video ids separate by comma in the same call. The extra call shouldn't consider exhausting because this is expected behavior on API v3:
Project Member #1 je...#google.com
That's the expected behavior, and not likely to change. Since the
search.list() method can return channels, videos, and playlists, only
properties that make sense for all of those resource types are
returned in the search responses. If you need to obtain any other
properties, making a follow-up request to, e.g., videos.list() is
required. Note that you can pass in up to 50 video ids to
videos.list(), so you can effectively look up an entire page's worth
of search.list() results in a single video.list() call.
If you try https://developers.google.com/youtube/v3/docs/videos/list#try-it , you set contentDetails,statistics as the part, you should able to get the following result:
"contentDetails": {
"duration": "PT20M38S",
"dimension": "2d",
"definition": "hd",
"caption": "false",
"licensedContent": false
},
"statistics": {
"viewCount": "191",
"likeCount": "7",
"dislikeCount": "0",
"favoriteCount": "0",
"commentCount": "0"
}
PT20M38S means 20 minutes and 38 seconds, based on ISO 8601(http://en.wikipedia.org/wiki/ISO_8601)
The best way for make this is:
if (!service) {
service = [[GTLServiceYouTube alloc] init];
service.shouldFetchNextPages = YES;
service.shouldFetchInBackground = YES;
service.retryEnabled = YES;
service.APIKey = #"AIzaSyDSO2JPnM_r9VcDrDJJs_d_7Li2Ttk2AuU";
}
[youtubeList removeAllObjects];
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id"];
query.maxResults = 50;
query.q = withText;
query.fields = #"items(id)";
query.order = #"viewCount";
query.type = #"video";
// query.videoDuration = #"long";//any-long-medium-short
__block NSInteger incrementRequest = 0;
[service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error) {
NSLog(#"Error is!! = %#", error.localizedDescription);
return;
}
GTLYouTubeVideoListResponse *idsResponse = object;
for (GTLYouTubeVideoListResponse *videoInfo in object) {
[youtubeList addObject:videoInfo.JSON];
GTLQueryYouTube *query2 = [GTLQueryYouTube queryForVideosListWithIdentifier:[[videoInfo.JSON valueForKey:#"id"] valueForKey:#"videoId"] part:#"id,contentDetails,snippet,statistics"];
query2.maxResults = 1;
query2.fields = #"items(id,contentDetails,snippet,statistics)";
query2.order = #"viewCount";
[service executeQuery:query2 completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error) {
NSLog(#"Error is!! = %#", error.localizedDescription);
return;
}
GTLYouTubeVideoListResponse *detalhe = object;
for (NSMutableDictionary *tmpDict in youtubeList) {
if ([[[tmpDict valueForKey:#"id"] valueForKey:#"videoId"] isEqualToString:[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"id"]]) {
[tmpDict removeObjectForKey:#"id"];
//condition personal
if (![Utils parseISO8601TimeIsGrater30:[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"contentDetails"] valueForKey:#"duration"]]) {
BOOL isBlockedInUs = NO;
for (NSString *countryRestric in [[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"contentDetails"] valueForKey:#"regionRestriction"] valueForKey:#"blocked"]) {
if ([countryRestric isEqualToString:#"US"]) {
isBlockedInUs = YES;
break;
}
}
if (!isBlockedInUs) {
[tmpDict addEntriesFromDictionary:detalhe.JSON];
[tmpDict setValue:[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"snippet"] valueForKey:#"publishedAt"] forKey:#"publishedAt"];
} else {
[youtubeList removeObject:tmpDict];
}
} else {
[youtubeList removeObject:tmpDict];
}
break;
}
}
incrementRequest ++;
if ([idsResponse.items count] == incrementRequest) {
//Finish
[self.tableView reloadData];
}
}];
}
}];

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.

Invalid touchJSON string

I get an invalid JSON string, which contains ; ( characters. Any guess what is going on?
My Code:
-(void)getJSONFeed {
// Create the URL & Request
NSURL *feedURL = [NSURL URLWithString:
#"http://maps.googleapis.com/maps/api/geocode/json? address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true"];
NSURLRequest *request = [NSURLRequest requestWithURL:feedURL];
// Example connection only. Add Timeouts, cachingPolicy in production
[NSURLConnection connectionWithRequest:request delegate:self ];
// init the jsonData Property
jsonData = [[NSMutableData data] retain];
}
// NSURLConnection Delegate Methods. You would want to include more for error handling //
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSMutableData *)data {
NSLog(#"Recieving Data...");
// Append the incomming data as it is received
[jsonData appendData:data];
NSLog(#"%#",jsonData);
}
-(NSDictionary *)parseJSON:(NSMutableData *)data {
NSLog(#"Parsing JSON");
NSError *error = nil;
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:data error:&error];
return dictionary;
}
// Parse JSON results with TouchJSON. It converts it into a dictionary.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Fininshed Loading...");
NSDictionary * feedDictionary = [self parseJSON:jsonData];
NSLog(#"JSON as NSDictionary: %#", feedDictionary);
}
{
results = (
{
"address_components" = (
{
"long_name" = 1600;
"short_name" = 1600;
types = (
"street_number"
);
},
{
"long_name" = "Amphitheatre Pkwy";
"short_name" = "Amphitheatre Pkwy";
types = (
route
);
},
{
"long_name" = "Mountain View";
"short_name" = "Mountain View";
types = (
locality,
political
);
},
{
"long_name" = "San Jose";
"short_name" = "San Jose";
types = (
"administrative_area_level_3",
political
);
},
{
"long_name" = "Santa Clara";
"short_name" = "Santa Clara";
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = California;
"short_name" = CA;
types = (
"administrative_area_level_1",
political
);
},
{
"long_name" = "United States";
"short_name" = US;
types = (
country,
political
);
},
{
"long_name" = 94043;
"short_name" = 94043;
types = (
"postal_code"
);
}
);
"formatted_address" = "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA";
geometry = {
location = {
lat = "37.422782";
lng = "-122.085099";
};
"location_type" = ROOFTOP;
viewport = {
northeast = {
lat = "37.4259296";
lng = "-122.0819514";
};
southwest = {
lat = "37.4196344";
lng = "-122.0882466";
};
};
};
types = (
"street_address"
);
}
);
status = OK;
}
UPDATE:
Somehow it interprets it as a Property list. The format seems to be similar to the original NeXTSTEP format with = ;
I'm not 100% sure what the question is. You do a valid HTTP connection, which makes a meaningful request from Google (if you delete the six spaces in the middle that are almost certainly a result of the code copy and paste to here). You accumulate the result. In the given code you appear to leak the object jsonData, but I assume that's irrelevant to the question.
You use the CJSONDeserializer object which I've not heard of but seems to be commonly mentioned on Google so is probably trustworthy. It returns a valid NSDictionary. You print the dictionary and it has the correct results in it.
Is the confusion just that when you print the dictionary to the console, it doesn't look identical to the JSON you received? If so then that's because it no longer has any concept that it came from JSON and Cocoa predates the JSON standard and hence doesn't use it for logging.
In any case, feedDictionary is a valid dictionary. The following:
NSLog(#"%#", [feedDictionary objectForKey:#"status"]);
Would print the string 'OK'. This:
NSArray *addressComponents = [feedDictionary objectForKey:#"address_components"];
for(NSDictionary *component in addressComponents)
{
NSLog(#"%#", [component objectForKey:#"long_name"]);
}
Would print the strings '1600', 'Amphitheatre Pkwy', 'Mountain View', 'San Jose', 'Santa Clara', 'California', 'United States', '94043' in that order.
If you want to print the raw JSON to the console, you probably want something like this (assuming the result comes back as UTF8):
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Fininshed Loading...");
NSString *feedString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"JSON was: %#", feedString);
[feedString release];
/*NSDictionary * feedDictionary = [self parseJSON:jsonData];
NSLog(#"JSON as NSDictionary: %#", feedDictionary); */
}
Though then you'll still need to parse it to a dictionary to get meaningful results from it.

Using JSON Framework on iPhone - HELP!

Currently I am using the following code to parse the JSON link sent. This is how I also send a GET call to the Google Reader API for an upcoming iPhone application of mine.
- (NSArray *)subscriptionList
{
if(!cookies && [cookies count] == 0) {
[self requestSession];
}
NSString * url = #"http://www.google.com/reader/api/0/subscription/list?output=json&client=scroll";
ASIHTTPRequest * request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
[request setRequestMethod:#"GET"];
[request setRequestCookies:cookies];
[request addRequestHeader:#"Authorization" value:[NSString stringWithFormat:#"GoogleLogin auth=%#", [self auth]]];
[request startSynchronous];
subfeeds = [NSMutableArray array];
// Create new SBJSON parser object
SBJSON *parser = [[SBJSON alloc] init];
if ([request responseStatusCode] == 200) {
NSData * sixty = [request responseData];
NSString * body = [[NSString alloc] initWithData:sixty encoding:NSUTF8StringEncoding];
if (body) {
NSArray *feeds = [parser objectWithString:body error:nil];
NSLog(#"Array Contents: %#", [feeds valueForKey:#"subscriptions"]);
NSLog(#"Array Count: %d", [feeds count]);
NSDictionary *results = [body JSONValue];
NSArray *ohhai = [results valueForKey:#"subscriptions"];
for (NSDictionary *title in ohhai) {
subTitles = [title objectForKey:#"title"];
NSLog(#"title is: %#",subTitles);
}
}
}
return subfeeds;
[subTitles release];
[parser release];
}
I can successfully parse the JSON using the above code, and it successfully outputs the titles into NSLog. In my RootViewController.m, I call the following to grab this -(NSArray *)subscriptionList.
-(void)viewDidAppear:animated {
GoogleReader * reader = [[GoogleReader alloc] init];
[reader setEmail:gUserString];
[reader setPassword:gPassString];
//feedItems is a NSArray where we store the subscriptionList NSArray
feedItems = [reader subscriptionList];
//NSString *feedTitle = [];
NSLog(#"%#", feedItems);
[reader release];
// the rest of the function
}
The code above successfully works with the credentials entered. As you can see there is also a commented NSString called feedTitle. This is where I want to pull the #"title" from the parsed JSON but I do not know how to call it.
Any help would be greatly appreciated!
This is what the JSON source looks like:
{"subscriptions":
[
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""}
]
}
I'm interested in only the "title" node.
Well, it would help if you added the source JSON but it's quite easy to grasp how SBJSON parses incoming JSON.
Just an example:
{ "myOutDict" : { "key1": "val1" , "key2" : "val2"} }
This JSON String would be parsed so you can access it by using this code
NSDictionary* myOuterdict = [feeds valueForKey:#"myOutDict"]);
NSString* val1 = [myOuterdict valueForKey:#"key1"]);
NSString* val2 = [myOuterdict valueForKey:#"key2"]);
Edit: Checked my personal Google Reader feed:
The JSON looks like this
{
"subscriptions": [{
"id": "feed/http://adambosworth.net/feed/",
"title": "Adam Bosworth's Weblog",
"categories": [],
"sortid": "0B5B845E",
"firstitemmsec": "1243627042599"
},
{
"id": "feed/http://feeds.feedburner.com/zukunftia2",
"title": "Zukunftia",
"categories": [],
"sortid": "FCABF5D4",
"firstitemmsec": "1266748722471"
}]
}
So the corresponding Objective C Code would be:
NSArray* subscriptions= [feeds valueForKey:#"subscriptions"]);
foreach(NSDictionary* item in subscriptions) {
// Do stuff
// NSString* title = [item valueForKey:#"title"]
// NSString* id = [item valueForKey:#"id"]
}
I'm not sure I understand the question. Are you trying to get a title for the feed as a whole, or per-item? Because I can't see a title property for the subscriptions array in the source JSON.