Get values out of data from NSJSONSerialization - ios

I have some JSON data which is pulled from a URL. The code I have written works fine to download the JSON and parse it, but I cannot seem to access it how I need too, especially where the data is contained as a sub-element of another one.
Here is the JSON format:
{
address = "<null>";
city = "<null>";
country = UK;
"country_code" = GB;
daylight = 1;
for = daily;
items = (
{
asr = "5:22 pm";
"date_for" = "2013-7-1";
dhuhr = "1:01 pm";
fajr = "2:15 am";
isha = "11:47 pm";
maghrib = "9:24 pm";
shurooq = "4:39 am";
}
);
latitude = "50.9994081";
link = "http://muslimsalat.com/UK";
longitude = "0.5039011";
"map_image" = "http://maps.google.com/maps/api/staticmap?center=50.9994081,0.5039011&sensor=false&zoom=13&size=300x300";
"postal_code" = "<null>";
"prayer_method_name" = "Muslim World League";
"qibla_direction" = "119.26";
query = "51.000000,0.500000";
state = "<null>";
timezone = 0;
title = UK;
"today_weather" = {
pressure = 1020;
temperature = 14;
};
}
(These are Islamic prayer times.)
My Objective-C so far is this:
-(CLLocationCoordinate2D) getLocation{
CLLocationManager *locationManager = [[[CLLocationManager alloc] init] autorelease];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
return coordinate;
}
//class to convert JSON to NSData
- (IBAction)getDataFromJson:(id)sender {
//get the coords:
CLLocationCoordinate2D coordinate = [self getLocation];
NSString *latitude = [NSString stringWithFormat:#"%f", coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:#"%f", coordinate.longitude];
NSLog(#"*dLatitude : %#", latitude);
NSLog(#"*dLongitude : %#",longitude);
//load in the times from the json
NSString *myURLString = [NSString stringWithFormat:#"http://muslimsalat.com/%#,%#/daily/5.json", latitude, longitude];
NSURL *url = [NSURL URLWithString:myURLString];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if(jsonData != nil)
{
NSError *error = nil;
id result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
NSArray *jsonArray = (NSArray *)result; //convert to an array
if (error == nil)
NSLog(#"%#", result);
NSLog(#"%#", jsonArray);
for (id element in jsonArray) {
NSLog(#"Element: %#", [element description]);
}
}
}
When running this code, the only output I get is a list of element names (address, city, country, so on). items is given, but not its child elements. I understand that this is what I am asking the code for with:
for (id element in jsonArray) {
NSLog(#"Element: %#", [element description]);
}
but I do not know how to move onto the next step.
The only data values which I require are in fact the times themselves (so, items>asr, items>dhuhr, etc).
How can I get these values themselves and then save them as values I can work with?
Thank you!

(...); - is Array
{...}; - is Dictionary
so your "element" is Dictionary
use objectForKey:
example:
for (id element in jsonArray) {
NSLog(#"Element asr: %#", [element objectForKey:#"asr"]); // or element[#"asr"]
}

NSArray *jsonArray = (NSArray *)result; //convert to an array
This doesn't 'convert', it's just you promising the compiler that result is really an NSArray. And in this case it's a lie.
Your code is currently just printing a list of the keys in the dictionary that is returned in the JSON. Try this to get to the list of items (it's an array so you need to deal with there possibly being multiple entries):
NSDictionary *result = [NSJSONSerialization ...
for (NSDictionary *itemDict in result[#"items"]) {
NSLog(#"item: %#", itemDict);
}
Then you can extract the times.

You can extract info by following:
NSError* error = nil;
NSDictionary *userInfo; //your main data
if([NSJSONSerialization class])
userInfo = [NSJSONSerialization JSONObjectWithData:[request responseData] options:kNilOptions error:&error];
//to extract items
NSDictionary *items = [[[userInfo objectForKey:#"items"] JSONValue] objectAtIndex:0];

Related

How to retrieve specific value of key in json?

this is my json content.
[
{
"sha":"30eae8a47d0203ac81699d8fc2ab2632de2d0bba",
"commit":{
"author":{
"name":"Madhura Bhave",
"email":"mbhave#pivotal.io",
"date":"2017-03-23T23:14:32Z"
},
"committer":{
"name":"Madhura Bhave",
"email":"mbhave#pivotal.io",
"date":"2017-03-23T23:14:32Z"
},
"message":"Merge branch '1.5.x'",
}
}
]
and this is my main.i just want to retrieve key value from message and name,email,date from committer dictionary.i got stuck how to do that.
NSMutableArray *CommitArray = [[NSMutableArray alloc] init];
for (NSDictionary *CommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
commitDictObj.message = [CommitDictionary objectForKey:#"message"];
for (NSDictionary *CommitterDictionary in [CommitDictionary objectForKey:#"committer"]) {
Committer *author = [[Committer alloc] init];
author.name = [CommitterDictionary objectForKey:#"name"];
author.email = [CommitterDictionary objectForKey:#"email"];
author.date = [CommitterDictionary objectForKey:#"date"];
}
[CommitArray addObject:commitDictObj];
}
for (int i =0 ; i < [CommitArray count] ; i++){
CommitDict *commitDictObj = [CommitArray objectAtIndex:i];
NSLog(#"Commit Message: %#", commitDictObj.message);
}
return 0;
}
}
i try fetch the json and display it value of message,name,email and date.how can i log the value of message, name, email and date?
Your array contains a dictionary, and that dictionary contains the commit dictionary, not the commit dictionary directly. Replace that part of your code:
for (NSDictionary *CommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
With that:
for (NSDictionary *shaCommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
NSDictionary *CommitDictionary = [shaCommitDictionary objectForKey:#"commit"];
(1) Convert JSON to NSDictionary
NSData *jsonData= ... // Assume you got the data already loaded
NSError *error = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
(2) Access the dictionary values (fast enumeration available by now!!
NSString *message = dictionary[#"message"];
NSDictionary *author = dictionary[#"author"];
NSString *name = author[#"author"];
NSString *email = author[#"author"];
NSString *date = author[#"author"];
// OR:
// NSString *name = dictionary[#"author"][#"author"];
// NSString *email = dictionary[#"author"][#"author"];
// NSString *date = dictionary[#"author"][#"author"];
And thats it. I think the tricky thing is to get the JSON Data to the NSDictionary?
See here: https://stackoverflow.com/a/30561781/464016

New to JSON API how to access the values in objective-c?

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);
}

Show Location string using latitude and longitude

I am using this method to show the string of location using current location latitude and longitude but it is showing differently
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",location.coordinate.latitude, location.coordinate.longitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
NSData *data = [locationString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *dic = [[json objectForKey:#"results"] objectAtIndex:0];
NSArray* arr = [dic objectForKey:#"address_components"];
//Iterate each result of address components - find locality and country
NSString *cityName;
NSString *countryName;
for (NSDictionary* d in arr)
{
NSArray* typesArr = [d objectForKey:#"types"];
NSString* firstType = [typesArr objectAtIndex:0];
if([firstType isEqualToString:#"locality"])
cityName = [d objectForKey:#"long_name"];
if([firstType isEqualToString:#"country"])
countryName = [d objectForKey:#"long_name"];
}
NSString* locationFinal = [NSString stringWithFormat:#"%#,%#",cityName,countryName];
NSLog(#"Final Location %# ",locationFinal);
but final location is showing this type :-
Final Location नठदिलà¥à¤²à¥,India
Why it is showing this type? Can anyone know about this.
Please supply the language with the API params. If language is not supplied, the geocoder attempts to use the preferred language as specified in the Accept-Language header, or the native language of the domain from which the request is sent.
So please replace the code as with the language parameter as like this.
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false&language=en",location.coordinate.latitude, location.coordinate.longitude];
and try again.
I believe that is an uninitialzed variable which is pointing into random memory.
Try:
NSString *cityName = nil;
NSString *countryName = nil;
Short-circuit your for loop:
for (NSDictionary* d in arr)
{
// Add this after the existing code:
if (cityName && countryName)
break;
}
and check for errors before presenting the results:
if (cityName && countryName) {
NSString* locationFinal = [NSString stringWithFormat:#"%#,%#",cityName,countryName];
NSLog(#"Final Location %# ",locationFinal);
} else {
NSLog(#"Failed to find location");
}
Finally your JSON-processing code does no error-checking at all. That's a mistake.

How To Get Particular Values From JSON and Plot on Map view Using Objective C?

I need to get particular values from below JSON response, The values are I have mentioned below
Reg no: (Need to show callout)
Lat : (Need to use drop pin on map)
Long : (Need to use drop pin on map)
Name : (Need to show callout)
Age : (Need to show callout)
NOTE : The school of array values getting from server so It will Increase based on A , B and C categories. Its not static!
{
A = {
school = (
{
reg_no = 1;
latitude = "22.345";
longitude = "-12.4567";
student = (
{
name = "akila";
age = "23";
}
);
city = "<null>";
state = TN;
},
{
reg_no = 2;
latitude = "22.345";
longitude = "-12.4567";
student = (
{
name = "sam";
age = "23";
}
);
city = "<null>";
state = TN;
}, {
reg_no = 3;
latitude = "22.345";
longitude = "-12.4567";
student = (
{
name = "lansi";
age = "23";
}
);
city = "<null>";
state = TN;
}
);
Schoolname = "Good School";
categories = school;
};
}
My Code (Below code not working) :
if (data) {
NSError *error;
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves | NSJSONReadingMutableContainers error:&error];
NSDictionary *response = JSON[#"response"];
for (NSDictionary *entry in response[#"A"][#"school"]) {
NSString *regNo = entry[#"reg_no"];
NSString *name = entry[#"student"][#"name"];
NSString *age = entry[#"student"][#"age"];
double latitude = [entry[#"latitude"] doubleValue];
double longitude = [entry[#"longitude"] doubleValue];
MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init];
myAnnotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
myAnnotation.title = name;
myAnnotation.subtitle = [NSString stringWithFormat:#"Reg: %#, Age: %#", regNo, age];
[mapView addAnnotation:myAnnotation];
}
Try NSJSONSerialization
NSError *e = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#", e);
} else {
for(NSDictionary *item in jsonArray) {
NSLog(#"Item: %#", item);
}
}
You can use NSJSONSerialization to parse the JSON, then you can access the values you need in a loop using Objective-C's subscripting syntax. Once you have all these, you can add the entries as MKAnnotations on an MKMapView to get what you want. Note that MKAnnotation is a protocol, so you'll need to create a class that implements it.
MKMapView *mapView = [MKMapView new];
NSDictionary *parsedJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
for (NSDictionary *entry in parsedJSON[#"A"][#"school") {
NSString *regNo = entry[#"reg_no"];
NSString *name = entry[#"student"][#"name"];
NSString *age = entry[#"student"][#"age"];
double latitude = [entry[#"latitude"] doubleValue];
double longitude = [entry[#"longitude"] doubleValue];
id<MKAnnotation> annotation = [/*class implementing MKAnnotation*/ new];
annotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
annotation.title = name;
annotation.subtitle = [NSString stringWithFormat:#"Reg: %#, Age: %#", regNo, age];
[mapView addAnnotation:annotation];
}
u should iterate entry[#"student"] to get the data of every student
entry[#"student"][#"name"] will get no data even if entry[#"student"] only have one
Your JSON file that you have provided for lacks of 'response' key in it. However, you are searching as NSDictionary *response = JSON[#"response"];. That could be the problem. Other than this, you can try NSDictionary's valueForKey: method to search deeper in your JSON.

Determine which time is next from a list of times

I have a JSON request which gives prayer times. How can I use Objective-C to work out which is next? The JSON looks like this:
{
address = "<null>";
city = "<null>";
country = UK;
"country_code" = GB;
daylight = 1;
for = daily;
items = (
{
asr = "5:22 pm";
"date_for" = "2013-7-1";
dhuhr = "1:01 pm";
fajr = "2:15 am";
isha = "11:47 pm";
maghrib = "9:24 pm";
shurooq = "4:39 am";
}
);
latitude = "50.9994081";
link = "http://muslimsalat.com/UK";
longitude = "0.5039011";
"map_image" = "http://maps.google.com/maps/api/staticmap?center=50.9994081,0.5039011&sensor=false&zoom=13&size=300x300";
"postal_code" = "<null>";
"prayer_method_name" = "Muslim World League";
"qibla_direction" = "119.26";
query = "51.000000,0.500000";
state = "<null>";
timezone = 0;
title = UK;
"today_weather" = {
pressure = 1020;
temperature = 14;
};
}
My code so far is:
-(CLLocationCoordinate2D) getLocation{
CLLocationManager *locationManager = [[[CLLocationManager alloc] init] autorelease];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
return coordinate;
}
//class to convert JSON to NSData
- (IBAction)getDataFromJson:(id)sender {
//get the coords:
CLLocationCoordinate2D coordinate = [self getLocation];
NSString *latitude = [NSString stringWithFormat:#"%f", coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:#"%f", coordinate.longitude];
NSLog(#"*dLatitude : %#", latitude);
NSLog(#"*dLongitude : %#",longitude);
//load in the times from the json
NSString *myURLString = [NSString stringWithFormat:#"http://muslimsalat.com/%#,%#/daily/5.json", latitude, longitude];
NSURL *url = [NSURL URLWithString:myURLString];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if(jsonData != nil)
{
NSError *error = nil;
id result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
NSArray *jsonArray = (NSArray *)result; //convert to an array
if (error == nil)
NSLog(#"%#", result);
NSLog(#"%#", jsonArray);
for (id element in jsonArray) {
NSLog(#"Element asr: %#", [element objectForKey:#"asr"]);
}
}
}
How can I get the current time and determine which prayer comes next?
Thank you!
You need to get the 'items' dictionary using [result objectForKey:#"items"]. Then convert the string values to NSDate's using an NSDateFormatter. Then, iterate through the new dictionary and find the time with the smallest time interval to now using [currentDate timeIntervalSinceNow]. This is your next prayer.
Get a list of the dates, then use an NSPredicate to filter that list to dates >= [NSDate date], then sort it ascending. Then the first item in the filtered, sorted array will be the next date.
Read Apple's Date and Time Programming Guide. You will find methods to convert you string times ("2:15am" etc.) into NSDate objects, methods to get the current date and time (e.g. [NSDate new] return the current date and time), and methods for comparing date/times so you can find the next one.

Resources