3

I have the following code to download a JSON file from my server:

- (void) queryAPI:(NSString*)query withCompletion:(void (^) (id json))block{
    NSURL *URL = [NSURL URLWithString:@"http://myAPI.example/myAPIJSONdata"];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    op.responseSerializer = [AFJSONResponseSerializer serializer];
    [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        block(responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
        block(nil);
    }];
    [[NSOperationQueue mainQueue] addOperation:op];
}

and the JSON file is like the following example:

{
    "dict":{
        "first key": [val1, val2, val3],
        "second key": [val1, val2, val3],
        "third key": [val1, val2, val3],
        "fourth key": [val1, val2, val3]
     }
}

I need to keep the keys at the same order they come on JSON file, but when I enumerate the returned NSDictionary with [dict allKeys], I get the keys disordered, like this:

fourth key    
second key    
first key    
third key

I also tried to use [dict keyEnumerator] but the result is exactly the same.

Is there any way to keep the keys at the same order they are on JSON file?

javsmo
  • 1,337
  • 1
  • 14
  • 23
  • 1
    An Dictionary don't need to be "ordered" since it's not an array, it works with the Key/Value system. – Larme Mar 18 '14 at 14:22
  • Ok, I understand that. But how can I get the keys at the same order? – javsmo Mar 18 '14 at 14:23
  • 1
    You need to store ordered items in array. – Avt Mar 18 '14 at 14:26
  • This question has been asked so many times ... A dictionary is an *unordered* collection. End of story. Arrays are ordered collections. – HAS Mar 18 '14 at 16:00
  • I agree that in this case I don't need a Dictionary, because I can change the webservice to return an array and solve this problem, but there are some cases when you need to keep the insertion order on a Dictionary. Other implementations (PHP for example) save the insertion order and enumerate with this order. What's the problem in having this feature? – javsmo Mar 18 '14 at 16:09
  • No, you don't. JSON objects (which are mapped to NSDictionary) are _by definition_ unordered. A JSON object with keys A, B, C and another JSON object with keys B, C, A are _identical_. There is no difference. – gnasher729 May 22 '14 at 16:16

1 Answers1

2

NSDictionary in Cocoa does not keep order of elements. So using AFJSONResponseSerializer it is impossible to keep the keys in the same order they are in JSON file. You have to parse JSON yourself or change JSON structure to use NSArray.

For example:

{
    [
        {"name" : "first key", "value" : [val1, val2, val3]},
        {"name" : "second key", "value" : [val1, val2, val3]},
        {"name" : "third key", "value" : [val1, val2, val3]},
        {"name" : "fourth key", "value" : [val1, val2, val3]}
     ]
}

UPDATE:

This thread could be useful for you Keeping the order of NSDictionary keys when converted to NSData with [NSJSONSerialization dataWithJSONObject:]

Community
  • 1
  • 1
Avt
  • 16,927
  • 4
  • 52
  • 72
  • Probably it depends of implementation. In objective C dictionaries are unordered. – Avt Mar 18 '14 at 14:47
  • 1
    You are correct. I also tried the same JSON data with `[NSJSONSerialization JSONObjectWithData:jsontext]` and the result is similar, also disordered. I can change the JSON, but I was hoping to avoid this, because other people are already using this file... – javsmo Mar 18 '14 at 15:03
  • 1
    This thread http://stackoverflow.com/questions/15125562/keeping-the-order-of-nsdictionary-keys-when-converted-to-nsdata-with-nsjsonseri could be interesting for you – Avt Mar 18 '14 at 15:12
  • Yes, it is really interesting. That class implemented by Cocoa with love has exactly the same idea than the PHP implementation. Too bad that JSON serializer doesn't use something like this. I'm convinced that I have to change the webservice to use an Array. – javsmo Mar 18 '14 at 15:20
  • If the order of elements is important to you, then YES. You need to send an array. An array / NSArray is an ordered collection, an object / NSDictionary is an unordered collection. – gnasher729 May 22 '14 at 16:17