Reputation: 3556
I have a JSON file with key/value-pairs for a list of countries and their country-codes. I'm reading it with Objective-C and want to present it in a UIPicker
.
Problem is, when I store the JSON data into a NSDictionary
, the original order is lost and the order of the UIPicker
elements is pretty arbitrary (I know, dictionaries don't have a particular order).
What's the easiest way to preserve to original order? Do I have to create two files, one with the country-codes and one with the country names in the same order and read both into an array? - I really wanna avoid that...
[Edit]
As per request, an excerpt of the JSON-Data (stored in a local file)
{"af":"Afghanistan",
"al":"Albania",
"dz":"Algeria",
"as":"American Samoa",
"ad":"Andorra",
"ao":"Angola",
"ai":"Anguilla",
"aq":"Antarctica",
"ag":"Antigua and Barbuda",
"ar":"Argentina",
"am":"Armenia",
"aw":"Aruba",
"ac":"Ascension Island (Atlantic ocean)",
"au":"Australia",
"at":"Austria",
"az":"Azerbaijan",
"bs":"Bahamas",
"bh":"Bahrain",
"bd":"Bangladesh",
"bb":"Barbados",
"by":"Belarus",
"be":"Belgium",
"bz":"Belize",
"bj":"Benin",
"bm":"Bermuda",
"bt":"Bhutan",
"bo":"Bolivia",
"ba":"Bosnia",
"bw":"Botswana",
"bv":"Bouvet Island (Atlantic ocean)",
"br":"Brazil",
... }
[Edit 2]
I'm using this code to read the JSON data and convert it to a NSDictionary
:
NSURL *jsonPath = [[NSBundle mainBundle] URLForResource:@"countries" withExtension:@"json"];
NSString *stringPath = [jsonPath absoluteString];
NSData *countriesJSON = [NSData dataWithContentsOfURL:[NSURL URLWithString:stringPath]];
NSDictionary *parsedJson = [NSJSONSerialization JSONObjectWithData:countriesJSON options:0 error:nil];
Upvotes: 0
Views: 985
Reputation: 9721
The issue of order and dictionaries often occurs when the dictionary needs to be displayed in a tableview. The established solution to this is to keep a separate array of dictionary keys alongside the dictionary. You can re-order the array as you (or the user) likes and do a two-stage fetch of dictionary entries via the array. This allows you to keep your original JSON format and internal storage properties/instance variables.
YourClass.m:
@interface MyClass ()
@property NSMutableArray *dictOrder;
@end
@implementation MyClass
- (void)getData
{
self.dict = // Get dictonary from JSON
self.dictOrder = [[self.dict allKeys] mutableCopy];
[self.dictOrder sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}
// UITableViewDataSource example
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Normal cell re-use stuff
NSString *key = self.dictOrder[indexPath.row];
NSString *country = self.dict[key];
// Populate cell
}
@end
Upvotes: 1
Reputation: 1451
If order is important and you have access to the JSON file, then you could change your JSON to be an array like so:
[
["Afghanistan", "AF"],
["Bangladesh", "BD"]
]
Then when you deserialize it, order will be preserved because the deserialized object will be an array of arrays.
If you don't have access to your JSON file then you could create this array of arrays from your Dictionary in code.
Edit
If you want both quick lookups and an ordering then it's tough to avoid using 2 data structures. With the JSON file you've submitted, it seems you want an array:
NSArray *countriesSorted = [parsedJson.allValues sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
However, it would be better for you to switch the order of values in your json file to be country-name:country-code. Then you could do
NSArray *countryCodesSorted = [parsedJson.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSString *firstCountryName = parsedJson[countryCodesSorted[0]];
Upvotes: 1
Reputation: 1346
You can change your JSON data to
[
{"af":"Afghanistan"},
{"al":"Albania"},
{"dz":"Algeria"},
{"as":"American Samoa"},
{"ad":"Andorra"},
{"ao":"Angola"},
{"ai":"Anguilla"},
...
]
Then use the code like:
NSURL *jsonPath = [[NSBundle mainBundle] URLForResource:@"sample" withExtension:@"json"];
NSData *countriesJSON = [NSData dataWithContentsOfURL:jsonPath];
NSMutableArray *countryArray = [NSJSONSerialization JSONObjectWithData: countriesJSON options:NSJSONReadingMutableContainers error:nil];
The JSON is converted to a ordered array called countryArray
. the elements of the countryArray
is a NSDictionary
instance.
Upvotes: 3