Melvin Roest
Melvin Roest

Reputation: 1502

iOS: JSON displays dictionary out of order. How to present a reordering?

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

Need JSON document that is generated to be in same order as objects inserted in NSMutableDictionary in iOS

Upvotes: 2

Views: 1840

Answers (3)

danh
danh

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

Wain
Wain

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

Grzegorz Krukowski
Grzegorz Krukowski

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

Related Questions