Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping the order of NSDictionary keys when converted to NSData with [NSJSONSerialization dataWithJSONObject:]

I have the following situation:

NSDictionary *params = @{
    @"Checkout" : @{
        @"conditions" : @{@"Checkout.user_id" : @1},
        @"order" : @{@"Checkout.id" : @"DESC"}
    },
    @"PaymentState" : @[],
    @"Offer" : @[]
};

This dictionary contains params for a webservice request passing a JSON string with the webservice URL. I get the JSON string using NSJSONSerialization class, like this:

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

The problem is: jsonString "keys" is ordered differently from the original params dictionary keys order, like this:

{
"Offer":[],
"PaymentState":[],
"Checkout":{
    "conditions":{"Checkout.user_id":6},
    "order":{"Checkout.id":"DESC"}
}

}

That is, the "PaymentState" and "Offer" keys come first in jsonString, and i need maintain the original order. This is very important, like this:

{
"Checkout":{
    "conditions":{"Checkout.user_id":6},
    "order":{"Checkout.id":"DESC"}
},
"Offer":[],
"PaymentState":[]

}

So guys, how can i do that??

like image 802
Rodrigo Salles Avatar asked Feb 28 '13 00:02

Rodrigo Salles


3 Answers

I use OrderedDictionary from CocoaWithLove whenever I need to keep the order of my dictionary keys.

Basically, OrderedDictionary contains an NSMutableDictionary and an NSMutableArray for the keys inside it, to keep track of the order of the keys. It implements the required methods for subclassing NSDictionary/NSMutableDictionary and just "passes" the method call to the internal NSMutableDictionary.

like image 75
neilvillareal Avatar answered Oct 12 '22 00:10

neilvillareal


According to the JSON spec a JSON object is specifically unordered. Every JSON library is going to take this into account. So even when you get around this issue for now, you're almost certainly going to run into issues later; because you're making an assumption that doesn't hold true (that the keys are ordered).

like image 39
Me1000 Avatar answered Oct 11 '22 23:10

Me1000


While NSDictionary and Dictionary do not maintain any specific order for their keys, starting on iOS 11 and macOS 10.13, JSONSerialization supports sorting the keys alphabetically (see Apple documentation) by specifying the sortedKeys option.

Example:

let data: [String: Any] = [
    "hello": "world",
    "a": 1,
    "b": 2
]

let output = try JSONSerialization.data(withJSONObject: data, options: [.prettyPrinted, .sortedKeys])
let string = String(data: output, encoding: .utf8)

// {
//  "a" : 1,
//  "b" : 2,
//  "hello" : "world"
// }
like image 30
Eneko Alonso Avatar answered Oct 11 '22 23:10

Eneko Alonso