2

I have a JSON array returning from a request.
Data is as such (it comes from external source and cannot be changed from server):

[{"clients":
{"name":"Client name here","telephone":"00000","email":"clientemail@hotmail.com","website":"www.clientname.com"}
}]

I receive the JSON array in this order.

I have the below Objective-C:

//jsonString is the json string inside type NSString.
NSMutableDictionary *tempDict = [jsonString JSONValue];
NSMutableDictionary *clients = [tempDict objectForKey:@"clients"];

for(NSString *key in clients) {
        id value = [tempDict objectForKey:key]; 
            for(NSString *itemKey in key) {
                NSLog(@"ITEM KEY %@: ",itemKey);

            }
}

The order it prints keys is:
telephone
email
name
web site

I need it to print how it is received (eg):
name
telephone
email
web site

I have read that Dictionaries are unsorted by definition so am happy to use an Array instead of a dictionary.

But I have seen SEVERAL threads on StackOverflow regarding possible solution (using keysSortedByValueUsingSelector):
Getting NSDictionary keys sorted by their respective values
Can i sort the NSDictionary on basis of key in Objective-C?
sort NSDictionary keys by dictionary value into an NSArray
Can i sort the NSDictionary on basis of key in Objective-C?

I have tried them and am getting nowhere. Not sure if it is just my implementation which is wrong.

I tried (attempt 1):

NSArray *orderedKeys = [clients keySortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){
    return [obj1 compare:obj2];
}];

for(NSString *key in orderedKeys) {
        id value = [tempDict objectForKey:key]; 
            for(NSString *keyThree in key) {
                NSLog(@"API-KEY-ORDER %@: ",keyThree);

            }
}

Receive error: [__NSArrayM keySortedByValueUsingComparator:]: unrecognized selector sent to instance.

Also tried (attempt 2):

NSArray *sortedKeys = [[clients allKeys] sortedArrayUsingSelector: @selector(compare:)];
NSMutableArray *sortedValues = [NSMutableArray array];
for (NSString *key in sortedKeys){
    [sortedValues addObject: [tempDict objectForKey: key]];
    //[sortedValues addObject: [all objectForKey: key]]; //failed
}

But another error on selector even though clients is a NSMutableDictionary.

[__NSArrayM allKeys]: unrecognized selector sent to instance 0x4b6beb0

I am at the point where I think I am going to iterate over the NSMutableDictionary and manually place them into a new NSMutableArray in the correct order.

Any ideas would be very much appreciated?
OR anybodies code snippet attempt at my problem would be equally appreciated.

Community
  • 1
  • 1
Craig Taub
  • 4,169
  • 1
  • 19
  • 25
  • It appears as if `clients` is an `NSArray` and you're trying to perform `NSDictionary`'s selectors on it – Eli Ganem Apr 11 '13 at 15:42
  • yes I do not undersand why it is thinking this. You can see above `clients` is an `NSMutableDictionary`. – Craig Taub Apr 11 '13 at 15:44
  • Place a breakpoint after `clients` is initiated and type `po clients` in the console. What class does the console show? – Eli Ganem Apr 11 '13 at 15:48
  • says `<__NSArrayM 0x4b7c590>( )` with all JSON inside brackets. same even when I use `NSMutableDictionary *clients = [[NSMutableDictionary alloc] init];` and then `clients = [tempDict objectForKey:@"clients"];` – Craig Taub Apr 11 '13 at 15:51
  • Then it's an array. Can you please post the complete json you're parsing? The json in your question seems partial, since it's an array. – Eli Ganem Apr 11 '13 at 15:52
  • very confused why it thinks its an array...cant post complete json as its huge...when I do same for `tempDict` it prints all json but without a type given..the items are the same for complete json but there are more of them (obv)..e.g `[{"client":{ },{ }, { } }]` – Craig Taub Apr 11 '13 at 15:57
  • By the way, I'm pretty sure that `tempDict` and `clients` are NOT mutable. That could explain the exceptions you're seeing. – Eli Ganem Apr 11 '13 at 16:02
  • ah...when I do above I see `Incompatible types in initialization` for `clients` object. Will try same without mutable. – Craig Taub Apr 11 '13 at 16:08
  • Ignore the code change I suggested. Change the type from `NSMutableDictionary` to `NSDictionary` and fix any warning you might get. – Eli Ganem Apr 11 '13 at 16:10
  • both now `NSDictionary` but breakpoint still says `<__NSArrayM 0x4b921c0>`.. so confusing but appreciate ur help... – Craig Taub Apr 11 '13 at 16:11
  • Put the json on http://snipt.org/ or any other site and send the link. I'm sure that a quick look at the json will clarify things. – Eli Ganem Apr 11 '13 at 16:17
  • I have validated the json. It is private data for now so unfortunately cant publish it. but it is as described above. I will look at setting up the same code with the small snipped I mentioned at top of question to see if same issues. – Craig Taub Apr 11 '13 at 16:21

2 Answers2

2

Not only is NSDictionary in principle unordered, but so are JSON objects. These JSON objects are identical:

[{"clients":
{"name":"Client name here","telephone":"00000","email":"clientemail@hotmail.com","website":"www.clientname.com"}
}]

[{"clients":
{"website":"www.clientname.com","name":"Client name here","telephone":"00000","email":"clientemail@hotmail.com"}
}]

If the server wants to have ordered keys, it needs to send an array. Of course you can just use the keysSortedByValueUsingComparator: method to get the keys in a sorted order.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
1

First, the exception you're seeing is because the selector name is incorrect. You should use keysSortedByValueUsingComparator. Second, you can't sort the keys, because the order in which you're getting them from the server doesn't seem to be in any particular order. If you MUST have them in that order, then send them from the server with a tag ("index") and then sort by this tag.

Eli Ganem
  • 1,479
  • 1
  • 13
  • 26