使用[NSJSONSerialization dataWithJSONObject:]转换为NSData时保持NSDictionary键的顺序

时间:2013-02-28 00:58:41

标签: ios objective-c cocoa-touch

我有以下情况:

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

此字典包含传递带有Web服务URL的JSON字符串的Web服务请求的参数。我使用NSJSONSerialization类获取JSON字符串,如下所示:

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

问题是:jsonString“keys”的顺序与原来的params字典键顺序不同,如下所示:

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

}

也就是说,“PaymentState”和“Offer”键在jsonString中排在第一位,我需要维护 原始订单。这非常重要,如下:

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

}

那么伙计们,我怎么能这样做?

3 个答案:

答案 0 :(得分:10)

每当我需要保持字典键的顺序时,我都会使用OrderedDictionary from CocoaWithLove

基本上,OrderedDictionary包含NSMutableDictionaryNSMutableArray内部的密钥,以跟踪密钥的顺序。它实现了子类化NSDictionary / NSMutableDictionary所需的方法,只是将方法调用“传递”到内部NSMutableDictionary

答案 1 :(得分:10)

根据JSON spec,JSON对象是特别无序的。每个JSON库都会考虑到这一点。因此,即使你现在解决这个问题,你几乎肯定会在以后遇到问题;因为你做的假设不成立(按键是有序的)。

答案 2 :(得分:4)

虽然NSDictionaryDictionary没有为其密钥维护任何特定订单,但从iOS 11和macOS 10.13开始,JSONSerialization支持按字母顺序对密钥进行排序(see Apple documentation)通过指定sortedKeys选项。

示例:

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"
// }