NSJSONSerialization parsing data issue - ios

I am parsing below data:-
NSURL *URL = [NSURL URLWithString:#"http://maps.googleapis.com/maps/api/directions/json?origin=40.714353,-74.005973&destination=40.650000,-73.950000&sensor=false&units=metric&mode=transit&departure_time=1396594530&alternatives=true"];
NSData* data = [NSData dataWithContentsOfURL:URL];
NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
Only part of Result not full result showing:
2014-04-04 15:24:10.036 Animation[478:907] {
routes = (
{
bounds = {
northeast = {
lat = "40.715478";
lng = "-73.94947789999999";
};
southwest = {
lat = "40.6497484";
lng = "-74.01035299999999";
};
};
copyrights = "Map data \U00a92014 Google";
legs = (
{
"arrival_time" = {
text = "03:35"; <<----- missing "am"
"time_zone" = "America/New_York";
value = 1396596948;
};
"departure_time" = {
text = "03:02";<<----- missing "am"
"time_zone" = "America/New_York";
value = 1396594936;
};`
when use this on simulator Correct result is coming, again showing part of response :-
{
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 40.715478,
"lng" : -73.94947789999999
},
"southwest" : {
"lat" : 40.6497484,
"lng" : -74.01035299999999
}
},
"copyrights" : "Map data ©2014 Google",
"legs" : [
{
"arrival_time" : {
"text" : "3:35am", <<----- showing "am"
"time_zone" : "America/New_York",
"value" : 1396596948
},
"departure_time" : {
"text" : "3:02am",<<----- showing "am"
"time_zone" : "America/New_York",
"value" : 1396594936
}
And same code is working on simulator fine.

You can pass the language when calling the maps api. Setting the language to en_US leads to the desired result:
NSURL *URL = [NSURL URLWithString:#"http://maps.googleapis.com/maps/api/directions/json?origin=40.714353,-74.005973&destination=40.650000,-73.950000&sensor=false&units=metric&mode=transit&departure_time=1396594530&alternatives=true&language=en_US"];

Related

Filter NSArray of NSDictionary , where the dictionary is of type <key , NSDictionary>

I have a NSArray like this
[ {
"268" : { "name" : "abc", "age" : "28"} }, {
"267" : { "name" : "xyz","age" : "25"} } ]
Now I want to filter it on behalf of keys (means 268 , 267 ).
Eg : If user search for 7 then it need to show
[ { "267" : { "name" : "xyz","age" : "25"} } ]
let filterText : String = "7"
let array : [Dictionary<String,Any>] = [ ["268" : [ "name" : "abc", "age" : "28"]], [ "267" : [ "name" : "xyz","age" : "25"] ] ]
let result = array.filter { (dictinory) -> Bool in
if let firstKey = dictinory.keys.first {
return firstKey.contains(filterText)
}
return false
}
You can use NSPredicate with block in Objective-C to filter it:
NSString *searchText = #"8";
NSArray *data = #[#{ #"268" : #{ #"name" : #"abc", #"age" : #"28"} }, #{ #"267" : #{ #"name" : #"xyz",#"age" : #"25"}}];
NSPredicate *predicate = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
NSDictionary *dict = (NSDictionary *)obj;
NSString *key = dict.allKeys.firstObject;
return [key containsString:searchText];
}];
NSArray *filteredData = [data filteredArrayUsingPredicate:predicate];

Extracting Require information from google map place api in IOS

I am working on GPS app in which i need to determine location based on longitude and Latitude of a place.I am able to determine the longitude and latitude and also location but i am getting the result of the google maps api call in json format in which there is a lot of data along with city name.
I have done like this.(I am using simulator so i have passed fixed latitude and longitude)
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297, 76.444017];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
locationString = [locationString stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSLog(#"%#",locationString );
The output string i am getting is
015-04-16 10:38:45.056 demolocationapp[690:12005] {
results : [
{
address_components : [
{
long_name : Rauni Kalan Link Road,
short_name : Rauni Kalan Link Rd,
types : [ route ]
},
{
**long_name : Rauni Kalan,
short_name : Rauni Kalan,
types : [ locality, political]**
},
{
long_name : Rupnagar,
short_name : Rupnagar,
types : [ administrative_area_level_2, political ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
},
{
long_name : 140102,
short_name : 140102,
types : [ postal_code ]
}
],
formatted_address : Rauni Kalan Link Road, Rauni Kalan, Punjab 140102, India,
geometry : {
bounds : {
northeast : {
lat : 30.8209903,
lng : 76.4550081
},
southwest : {
lat : 30.8178417,
lng : 76.44540219999999
}
},
location : {
lat : 30.8186057,
lng : 76.4507395
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.8209903,
lng : 76.4550081
},
southwest : {
lat : 30.8178417,
lng : 76.44540219999999
}
}
},
place_id : ChIJc8IoHwICEDkR38Ie5TOeGu0,
types : [ route ]
},
{
address_components : [
{
long_name : Rauni Kalan,
short_name : Rauni Kalan,
types : [ locality, political ]
},
{
long_name : Rupnagar,
short_name : Rupnagar,
types : [ administrative_area_level_2, political ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
},
{
long_name : 140102,
short_name : 140102,
types : [ postal_code ]
}
],
formatted_address : Rauni Kalan, Punjab 140102, India,
geometry : {
bounds : {
northeast : {
lat : 30.8219531,
lng : 76.4462614
},
southwest : {
lat : 30.81705139999999,
lng : 76.4414979
}
},
location : {
lat : 30.8192965,
lng : 76.44401660000001
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.8219531,
lng : 76.4462614
},
southwest : {
lat : 30.81705139999999,
lng : 76.4414979
}
}
},
place_id : ChIJ_f1PWh0CEDkRKlzFwhc62zo,
types : [ locality, political ]
},
{
address_components : [
{
long_name : 140102,
short_name : 140102,
types : [ postal_code ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : Punjab 140102, India,
geometry : {
bounds : {
northeast : {
lat : 30.869706,
lng : 76.47508049999999
},
southwest : {
lat : 30.7970006,
lng : 76.3335855
}
},
location : {
lat : 30.8288892,
lng : 76.4215988
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.869706,
lng : 76.47508049999999
},
southwest : {
lat : 30.7970006,
lng : 76.3335855
}
}
},
place_id : ChIJHX2_rA0BEDkR_QslHcc_M0g,
types : [ postal_code ]
},
{
address_components : [
{
long_name : Fatehgarh Sahib,
short_name : Fatehgarh Sahib,
types : [ administrative_area_level_2, political ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : Fatehgarh Sahib, Punjab, India,
geometry : {
bounds : {
northeast : {
lat : 30.8779699,
lng : 76.63427999999999
},
southwest : {
lat : 30.4275501,
lng : 76.0761799
}
},
location : {
lat : 30.6810924,
lng : 76.4100267
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.8779699,
lng : 76.63427999999999
},
southwest : {
lat : 30.4275501,
lng : 76.0761799
}
}
},
place_id : ChIJqf6CHWocEDkR4EljDGd5be8,
types : [ administrative_area_level_2, political ]
},
{
address_components : [
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : Punjab, India,
geometry : {
bounds : {
northeast : {
lat : 32.4981352,
lng : 76.92175809999999
},
southwest : {
lat : 29.537147,
lng : 73.8708879
}
},
location : {
lat : 31.1471305,
lng : 75.34121789999999
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 32.4981352,
lng : 76.92175809999999
},
southwest : {
lat : 29.537147,
lng : 73.8708879
}
}
},
place_id : ChIJVXOeVqpkGTkRYYijAzEmvY8,
types : [ administrative_area_level_1, political ]
},
{
address_components : [
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : India,
geometry : {
bounds : {
northeast : {
lat : 35.5087008,
lng : 97.395561
},
southwest : {
lat : 6.7535159,
lng : 68.162386
}
},
location : {
lat : 20.593684,
lng : 78.96288
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 35.5087008,
lng : 97.395561
},
southwest : {
lat : 6.7535159,
lng : 68.16288519999999
}
}
},
place_id : ChIJkbeSa_BfYzARphNChaFPjNc,
types : [ country, political ]
}
],
status : OK
}
I have put my Required data where type is locality,political in **Required Text **
How can i get that
Used this method
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat: #"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297, 76.444017]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray *arr=[[json valueForKeyPath:#"results.address_components"] objectAtIndex:0];
for (NSDictionary *dictAddress in arr)
{
if ([[dictAddress objectForKey:#"types"] count] > 0)
{
if([[[dictAddress objectForKey:#"types"] objectAtIndex:0] isEqualToString:#"locality"])
{
return [dictAddress objectForKey:#"long_name"];
}
else if([[[dictAddress objectForKey:#"types"] objectAtIndex:0] isEqualToString:#"political"])
{
return [dictAddress objectForKey:#"long_name"];
}
}
else
{
return #"";
}
}
return #"";
}
}
}];
Using this method you will find the name of the area which type start with "locality" or "political".
But i have took first object of the api response but if you need rathar than this , then put loop to take object of the json called.
Hope this will helps you.
You need to convert your string of the JSON object to an NSDictionary and then use key/value accessors to get each field.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat: #"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297, 76.444017]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray *results = [json valueForKey:#"results"];
for (NSDictionary *result in results)
{
NSLog(#"%#", [result valueForKey:#"formatted_address"]);
NSLog(#"%#", [result valueForKey:#"place_id"]);
// Etc...
}
}
}];
First off, I would use NSURLSessions and blocks to make network calls. The beauty of blocks is that if my network connection is poor my block will only get executed at after the call returns.
Then you need to convert your JSON to foundation objects that you can work with.
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297,76.444017];
NSURL *url = [NSURL URLWithString:urlString];
//Next we need a NSURLSession instance
NSURLSession *session = [NSURLSession sharedSession];
//All tasks (there are three, see documentation) are created from an NSURLSession instance
//We want a DataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//This "block" (of code) will be executed when the call is complete
//Serialize the JSON to Foundation objects
NSDictionary *geocodeDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//Parse through the JSON to get to where we want, address_components array
NSArray *resultsArray = geocodeDictionary[#"results"];
NSDictionary *resultsDictionary = resultsArray[0];
NSArray *addressComponents = resultsDictionary[#"address_components"];
//Declare variables to hold desired results
NSString *longName;
NSString *shortName;
//The address_components array contains many dictionaries,
//we loop through each dictionary and check the types array
for (NSDictionary *addressComponentDictionary in addressComponents) {
NSArray *typesArray = addressComponentDictionary[#"types"];
if ( [typesArray[0] isEqualToString:#"locality"]
&& [typesArray[1] isEqualToString:#"political"]) {
//the type IS locality and political
longName = addressComponentDictionary[#"long_name"];
shortName = addressComponentDictionary[#"short_name"];
}
}
//Test log to see we are correct
NSLog(#"%#", longName);
NSLog(#"%#", shortName);
}];
[dataTask resume];

How should i parse this JSON?

What would be the best way to parse this JSON object into a data object in Objective C?
{
"Properties" : {
"Property1" : {
"min" : 70.0,
"max" : 70.0
},
"Property2" : {
"min" : 0.41,
"max" : 0.41
},
"Property3" : {
"min" : 0.41,
"max" : 0.41
},
"Property4" : {
"min" : 0.41,
"max" : 0.41
}
}
The name "properties" will remain constant, but the name of properties inside this can change and so can the number of properties. For example, this could be;
{
"Properties":
"RandomNameOfProperty" : {
"min" : 0.41,
"max" : 0.41
},
"RandomNameOfProperty2" : {
"min" : 0.41,
"max" : 0.41
}
}
}
Edit: Corrected JSON format.
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
json = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableLeaves error: &e];
where data is your json data
Here is how you can transform you JSON to Objective-C
NSString *jsonString = #"{"name": "My name" ....}"
NSData *data = [#" " dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
NSError *er;
json = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableLeaves error: &er];
MyClassModel *my = [[MyClassModel alloc] init];
my.name = json[#"name"];
my.age = [json[#"age"] integerValue];
my.type = json[#"type"];
There are also many libraries that does dynamic parsing and transformation for you.
JSONModel is really good one. With it you code would look like this -
NSString* json = #"{"name": "My name" ....}" //(fetch here JSON from Internet)
NSError* err = nil;
MyClassModel* country = [[MyClassModel alloc] initWithString:json error:&err];

How do I filter array of dictionaries by dictionary key

Here is my JSON.This is for total 250 countries I listed only 3 below. here i need to do the thing is i have the parse the countries into seven different arrays based on continent.
{
"geonames" : [
{
"languages" : "ca",
"east" : 1.786542777831983,
"continent" : "EU",
"geonameId" : 3041565,
"population" : "84000",
"areaInSqKm" : "468.0",
"countryName" : "Andorra",
"south" : 42.42849259876837,
"countryCode" : "AD",
"capital" : "Andorra la Vella",
"isoAlpha3" : "AND",
"fipsCode" : "AN",
"isoNumeric" : "020",
"west" : 1.407186714111276,
"continentName" : "Europe",
"north" : 42.65604389629997,
"currencyCode" : "EUR"
},
{
"languages" : "ar-AE,fa,en,hi,ur",
"east" : 56.38166046142578,
"continent" : "AS",
"geonameId" : 290557,
"population" : "4975593",
"areaInSqKm" : "82880.0",
"countryName" : "United Arab Emirates",
"south" : 22.63332939147949,
"countryCode" : "AE",
"capital" : "Abu Dhabi",
"isoAlpha3" : "ARE",
"fipsCode" : "AE",
"isoNumeric" : "784",
"west" : 51.58332824707031,
"continentName" : "Asia",
"north" : 26.08415985107422,
"currencyCode" : "AED"
},
{
"languages" : "fa-AF,ps,uz-AF,tk",
"east" : 74.879448,
"continent" : "AS",
"geonameId" : 1149361,
"population" : "29121286",
"areaInSqKm" : "647500.0",
"countryName" : "Afghanistan",
"south" : 29.377472,
"countryCode" : "AF",
"capital" : "Kabul",
"isoAlpha3" : "AFG",
"fipsCode" : "AF",
"isoNumeric" : "004",
"west" : 60.478443,
"continentName" : "Asia",
"north" : 38.483418,
"currencyCode" : "AFN"
}
]
}
This is how you can filter your geonames array. the method filterArrayByADictionary gets an array and search criteria and returns filtered array of dictionaries.
-(NSArray *)filterArrayByADictionary:(NSArray *)aArray andKey:(NSString *)aPredicte
{
NSPredicate *filter = [NSPredicate predicateWithFormat:aPredicte];
return [aArray filteredArrayUsingPredicate:filter];
}
and you can call this method like this.
NSArray *AsiaCounties = [self filterArrayByADictionary: geonames andKey:#"continent = 'AS'"];
NSArray *EuropeCounties = [self filterArrayByADictionary: geonames andKey:#"continent = 'EU'"];
// rest of the continents...
Assuming you had taken this output in NSDictionary :
NSDictionary *mainDic;
NSMutableArray *arr = [NSMutableArray new];
NSMutableArray *arrcontinent1 = [NSMutableArray new];
NSMutableArray *arrcontinent2 = [NSMutableArray new];
arr = [mainDic valueForKey:#"geonames"];
for(int i=0; i<[arr count];i++){
NSDictionary *dic = [arr objectAtIndex:i];
if([[dic valueForKey:#"continent"] isEqualToString:#"EU"]){
[arrcontinent1 addObject:dic];
}
else if([[dic valueForKey:#"continent"] isEqualToString:#"AS"]){
[arrcontinent2 addObject:dic];
}
// and so on......
}

How to parse JSON multi-array

I need to parse the JSON file provided by Google Maps API
Then i use the AFNetworkingRequestHow to get the JSON response.
I built this dictionary:
NSDictionary *jsonDict = (NSDictionary *) JSON;
NSArray *rows = [jsonDict objectForKey:#"rows"];
But now, how can i reach the first value field of duration tag?
JSON File to parse:
{
"destination_addresses" : [ "San Francisco, CA, USA", "Victoria, BC, Canada" ],
"origin_addresses" : [ "Vancouver, BC, Canada", "Seattle, WA, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "1,527 km",
"value" : 1527251
},
"duration" : {
"text" : "15 hours 0 mins",
"value" : 54010
},
"status" : "OK"
},
{
"distance" : {
"text" : "112 km",
"value" : 111906
},
"duration" : {
"text" : "3 hours 1 min",
"value" : 10885
},
"status" : "OK"
}
]
}
}
Try
NSDictionary *jsonDict = (NSDictionary *) JSON;;
NSArray *rows = jsonDict[#"rows"];
NSDictionary *row = rows[0];
NSArray *elements = row[#"elements"];
NSDictionary *element = elements[0];
NSDictionary *duration = element[#"duration"];
NSInteger value = [duration[#"value"] integerValue];
[json objectForKey:#"elements"]
is an NSArray. You can't initialize an NSDictionary directly with an array.
(in JSON, { and } denote key-value pairs, like NSDictionary, whereas [ and ] delimit ordered lists like NSArray, that's why the mapping is done as it is...)
Following thinks can you understanding for development time so it may help lot.
You can use the following code:
NSString *valueString = [[[[[rows objectAtindex:0]objectForKey:#"elements" ]objectAtindex:0]objectForKey:#"duration"] objectForKey:#"value"];
//if you want integer value
NSInteger value = [valueString integerValue];

Resources