Mapping array to dictionary using object in array as key - ios

I'm using RestKit in my iOS app and I can't seem to get this to work. I have the following JSON array:
{
"id" : 1,
"streamable" : true
},
{
"id" : 2,
"streamable" : true
},
{
"id" : 3,
"streamable" : true
}
I would like to end up with a dictionary looking like this:
{
"1" : {
"id" : 1,
"streamable" : true
},
"2" : {
"id" : 2,
"streamable" : true
}
}
Where I use the id value as the dictionary's key. How would I map this using RestKit?

Assume, you have array of Disctionaries , iterate through the dictionaries and find for the id make this a new Dictionary
For Instance :
NSArray *arrDictionaries = // .....
NSDictionary *result =[[NSDictionary alloc]init];
for(NSDictionary *dict in arrDictionaries){
NSstring *key = [dict objectForKey:#"id"];
[result setObject:dict forKey:key];
}
Note : I've not tested

Related

Objective C - Issue when read JSON Key

Hi everyone I am working with a JSON file in my xCode project.
I can easily display the various JSON key but when I call a key it specifies my app crashes and I don't understand why ...
I was very careful to write the keys correctly but it keeps crashing ...
This is my example JSON file
{
"Università" : {
"uniID" : {
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"nome" : "Università per stranieri di Perugia",
"regione" : "Umbria"
},
"uniID" : {
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"nome" : "Università degli Studi Internazionali di Roma ( UNINT )",
"regione" : "Lazio"
},
}
}
When I try to recover the "name" key my app crashes, this is true even if I call "latitude" or "longitude" etc ...
Where am I doing wrong ?
These are the functions I use for reading the JSON file
-(void)setupUniversityLocation:(MKMapView *)mapView {
NSDictionary *dict = [self JSONUniversity];
NSArray *universityArray = [[dict objectForKey:#"Università"] objectForKey:#"uniID"];
for (NSDictionary *uni in universityArray) {
NSString *uniname = [uni objectForKey:#"nome"];
NSLog(#"uniname %#",uniname);
}
}
#pragma mark - Read JSON Data University
-(NSDictionary *)JSONUniversity {
NSString *path = [[NSBundle mainBundle] pathForResource:#"university" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
I also wanted to ask you how can I directly read the keys "name", "latitude" etc ... without where to invoke the "uniID" key? is it possible to bypass a category key?
There is no array in your json file. You should change json file to
{
"Università" : [
{
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"nome" : "Università per stranieri di Perugia",
"regione" : "Umbria"
},
{
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"nome" : "Università degli Studi Internazionali di Roma ( UNINT )",
"regione" : "Lazio"
}
]
}
Use [] to present array instead of {} and below code will work
-(void)setupUniversityLocation:(MKMapView *)mapView {
NSDictionary *dict = [self JSONUniversity];
NSArray *universityArray = [dict objectForKey:#"Università"];
for (NSDictionary *uni in universityArray) {
NSString *uniname = [uni objectForKey:#"nome"];
NSLog(#"uniname %#",uniname);
}
}
#pragma mark - Read JSON Data University
-(NSDictionary *)JSONUniversity {
NSString *path = [[NSBundle mainBundle] pathForResource:#"university" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
There is no Array in the example JSON you posted.
So in this line:
NSArray *universityArray = [[dict objectForKey:#"Università"] objectForKey:#"uniID"];
When you are assuming the output is an array, in actuality it's a dictionary.
If you put a log statement outputting the kind of class returned after that line:
NSLog(#"Kind of class returned from univeristyArray = %#", [universityArray class]);
It will return:
Kind of class returned from univeristyArray = __NSDictionaryI
Right now your structure of the JSON example you posted is:
Top Level Object (Dictionary)
"Università" (Dictionary)
"uniID" (Dictionary)
Another issue with this structure is that you have multiple values for the same key under the "Università" dictionary (i.e. multiple "uniID" which have different associated values)
If you have control over the JSON generated, you have a couple of different options depending on what you're attempting to do:
From your code, it looks like you're attempting to loop through all the "Università" and output their name -- and you're expecting them to be stored in an Array. In this case you'd want to change the "Università" data structure to an Array in the JSON.
Alternatively, make the "nome" value of the university the key for the lower level dictionaries and then fetch them by name (only if the universities names are going to be unique) -- this would be good if you have a large list of universities and you're attempting to only fetch specific ones (by name).
Example of #1:
university.json:
{
"Università" : [
{
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"nome" : "Università per stranieri di Perugia",
"regione" : "Umbria"
},
{
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"nome" : "Università degli Studi Internazionali di Roma ( UNINT )",
"regione" : "Lazio"
},
]
}
setupUniversityLocation:
-(void)setupUniversityLocation {
NSDictionary *dict = [self JSONUniversity];
NSArray *universityArray = [dict objectForKey:#"Università"];
for (NSDictionary *uni in universityArray) {
NSString *uniname = [uni objectForKey:#"nome"];
NSLog(#"uniname %#",uniname);
}
}
Example of #2:
university.json:
{
"Università" : {
"Università per stranieri di Perugia": {
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"regione" : "Umbria"
},
"Università degli Studi Internazionali di Roma ( UNINT )": {
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"regione" : "Lazio"
},
}
}
setupUniversityLocation:
-(void)setupUniversityLocation {
NSDictionary *dict = [self JSONUniversity];
NSDictionary *universityDictionary = [dict objectForKey:#"Università"];
// this is an example of looping through the entire dictionary
// typically you'd use objectForKey when accessing a specific university
for (NSString *universityNameKey in universityDictionary.allKeys) {
NSDictionary *specificUniDictionary = [universityDictionary objectForKey:universityNameKey];
NSLog(#"uniname %#",universityNameKey);
NSLog(#"latitudine %#", [specificUniDictionary objectForKey:#"latitudine"]);
NSLog(#"longitudine %#", [specificUniDictionary objectForKey:#"longitudine"]);
}
}
For most cases I would recommend going with the second option as if it's a large list it's going to be a lot quicker to find a specific item, but it definitely depends on your use case.

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];

Order of json format is getting changed

Order of json format is getting changed. I need the below format
{
"user_id": "",
"name": "",
"StDate": "07/16/2015 13:00",
"EdDate": "07/16/2015 13:00",
"detailed": [
{
"Stname": ""
},
]
}
What i am getting atlast is
{
"user_id" : "1",
"Detailed" : [
{
“Stname" : ""
},
"EdDate" : "08\/19\/2015 12:25:47",
"StDate" : "08\/19\/2015 12:25:47",
“name” : "",
}
After getting all values i am converting to json. I am using the following code.
NSError *error1;
NSString *jsonString1;
NSData *jsonData1 = [NSJSONSerialization dataWithJSONObject:dictjson1
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (! jsonData1) {
NSLog(#"Got an error: %#", error1);
} else {
jsonString1 = [[NSString alloc] initWithData:jsonData1 encoding:NSUTF8StringEncoding];
NSLog(#"converted json string is %#",jsonString1);
}
Please advice.
JSON has two structures: objects and arrays. Arrays are indexed by integers, and ordered. Objects are indexed by strings, and unordered. You can't enforce order on JSON objects; it is implementation-dependent. If you need to access object attributes in a certain order, enumerate the keys in this order in an array.

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];

iOS JSON parse trouble

How should I parse JSONs with format:
{
"1": {
"name": "Бекон",
"unit": "гр."
},
"2": {
"name": "Бульон куриный",
"unit": "ст."
}
}
and:
{
"recipeCode" : "00001",
"inCategory" : "12",
"recipe" : "Зимний тыквенный суп",
"difficulty" : 2,
"personCount" : 4,
"prepHour" : 1,
"prepMin" : 30,
"comments" : "При подаче добавить сметану, крутоны и присыпать сыром",
"ingredients" : {
"2" : 3,
"11" : 2,
"13" : 1,
"14" : 2,
"19" : 1
}
}
The second one I even didn't try... But with the first one I have some problems. I do this:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Ingredients" ofType:#"json"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
NSError *error = nil;
NSDictionary *ingredients = [NSJSONSerialization JSONObjectWithData:myData options:kNilOptions error:&error];
and than I have ingredient dictionary with two key/value pairs. Both of them contains key "1" and value "1 key/value pairs" and nothing about "name" or "unit" values.
Any help how to correctly parse such JSONs
You are parsing it correctly,and what you will have output will be there in the dictionary
The parsing gives output as objects as NSDictionary and array as NSArray
so in your case the key 1 and key 2 have value a NSDictionary itself
NSDictionary *dict1 = [ingredients objectForKey:#"1"];
NSDictionary *dict2 = [ingredients objectForKey:#"2"];
and value as
NSString *name=[dict1 objectForKey:#"name"];
NSString *unit=[dict1 objectForKey:#"unit"];

Resources