Reputation: 1502
Say we have the following dictionary:
dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:currentItem], @"item number",
[NSNumber numberWithInt:([[item valueForKey:@"section"] intValue]+1)], @"section number",
currentDate, @"date of item",
[NSNumber numberWithDouble:timeDifference], @"time difference in millis",
nil];
Then I get the following output:
{
"time difference in millis" : 5.220093071460724,
"section number" : 1,
"date of item" : "28/04/2014 15:56:54,234",
"item number" : 3
}
I use the following code to convert the dictionary to JSON:
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
jsonString = [jsonString stringByReplacingOccurrencesOfString:@"\\" withString:@""];
How can I manipulate the order in which the JSON string shows its keys. For example, I would like to have:
{
"item number" : 3,
"section number" : 1,
"date of item" : "28/04/2014 15:56:54,234",
"time difference in millis" : 5.220093071460724
}
or something else. The point is that I want control over this process. How do I get it? My first thought was writing a parser that shows the ordering in the way that I want.
Here are similar questions, but my emphasis is on manipulating the order instead of just recreating the order in which I put it from the dictionary.
JSON format: getting output in the correct order
Upvotes: 2
Views: 1840
Reputation: 62686
To restate the question: how to take an inherently unordered input, produce a string who's specification is inherently unordered, but control the ordering of that string.
Reformatting the dictionary as an array would let you control input ordering, but produce a different output format.
The only reason I can imagine wanting to do this is if wish to use the JSON string not as JSON, but just as a string. The question can then be restated as just lexically reformatting the string.
How general purpose must it be? Can we assume that the JSON has simple, scalar values? Then...
- (NSString *)reorderJSON:(NSString *)json keys:(NSArray *)orderedKeys {
NSArray *splitJson = [json componentsSeparatedByString:@","];
NSMutableArray *splitResult = [NSMutableArray array];
for (NSString *key in orderedKeys) {
for (NSString *splitPair in splitJson) {
if ([self jsonPair:splitPair hasKey:key]) {
NSString *trimmedSplitPair = [splitPair stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"{}"]];
[splitResult addObject:trimmedSplitPair];
}
}
}
NSString *joinedResult = [splitResult componentsJoinedByString:@","];
return [NSString stringWithFormat:@"{%@\n}", joinedResult];
}
- (BOOL)jsonPair:(NSString *)pair hasKey:(NSString *)key {
// pair should begin with double quote delimited key
NSString *trimmedPair = [pair stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *splitPair = [trimmedPair componentsSeparatedByString:@"\""];
return [splitPair[1] isEqualToString:key];
}
Call it like this:
- (void)testJson {
NSDictionary *d = @{ @"time difference in millis": @5.220093071460724,
@"section number": @1,
@"date of item" : @"28/04/2014 15:56:54,234",
@"item number": @3};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:d options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
NSArray *orderedKeys = @[ @"item number", @"section number", @"date of item", @"time difference in millis"];
NSString *result = [self reorderJSON:jsonString keys:orderedKeys];
NSLog(@"%@", result);
}
Upvotes: 1
Reputation: 119041
You shouldn't want that. Dictionaries have no order and writing some code that uses the order will just lead to problems in the future.
That said, if you want to, you can write your own code to generate the JSON string from your (ordered) array of keys and dictionary of values.
Upvotes: 0
Reputation: 19872
NSDictionary is not ordered by definition. Easiest will be to wrap everything into NSArray if you want to have same order.
Upvotes: 3