将 NSDictionary 转换为 Json String 会导致元素重新排序

Posted

技术标签:

【中文标题】将 NSDictionary 转换为 Json String 会导致元素重新排序【英文标题】:Converting NSDictionary to Json String causes re-ordering of elements 【发布时间】:2016-12-01 02:55:34 【问题描述】:

我正在尝试使用以下方法将 NSDictionary 对象转换为 json 字符串:

let data = try JSONSerialization.data(withJSONObject: data, options :[])
var string = String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))

然而,它按字母顺序重新排序各个元素,这就是 Swift 返回的内容:

"client-nonce":"4q7581q6CbkAlJAAajHuWFiLJTPKJLpk","timestamp":"1480560235","token":"5aeba5cb66644e8e739765632a23f2f98a4035f99306f46777c67cea652dad79","url":"http://api.uselinkthrow.local/api/me/stream/friend/links"

我想保留字典的制作顺序,因此返回:

"token":"5aeba5cb66644e8e739765632a23f2f98a4035f99306f46777c67cea652dad79","timestamp":"1480560235","client-nonce":"4q7581q6CbkAlJAAajHuWFiLJTPKJLpk","url":"http://api.uselinkthrow.local/api/me/stream/friend/links"

有人知道我该怎么做吗?

【问题讨论】:

世界就是这样运转的。此外,如果字典键不按顺序会有什么影响? HMAC 哈希值会有所不同 "有人知道我该怎么做吗?"你为什么要这样做?如果你能解释原因,那么人们或许能够提供明智的解决方案。如果你真的想这样做,那么字典(单独)是错误的数据结构。您需要一个数组,或者一个数组和字典的组合。字典本质上是无序的。数组是有序的。这适用于 JSON 以及 swift。但是,取决于您对“为什么?”的回答。问题,您最好继续使用字典,然后在需要时将其键操作成某种顺序。 【参考方案1】:

您不能也不应该依赖 JSON 对象中元素的顺序。

JSON Object是键值对,没有顺序,不能排序,最后的顺序无所谓

更多详情请查看json.org

【讨论】:

是的,我想到了这一点,但不知道是否可以覆盖它,我将不得不处理这个服务器端。谢谢 我们为解决这个问题所做的是在将字典转换为 JSON 之前计算排序键及其值的哈希值。这不是一个理想的解决方案,但只要服务器和客户端算法匹配哈希就会。 @JohnDoe 我认为唯一的方法是自己构造 JSON 字符串,而不是依赖 JSONSerialization。因为最终您将发送到服务器端的数据将是字符串格式。【参考方案2】:

正如其他人所提到的,它是一本字典,并非旨在提供有序键。它旨在进行快速哈希查找,因此请继续使用它来将事物按正确的顺序排列。

我不确定为什么你想要某种有序的字符串,所以这只是一个示例,供你按照你想要的顺序打印字符串:

if let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] 
    ["token", "timestamp", "client-nonce", "url"].forEach( print(String(describing: json?[$0])) )

【讨论】:

【参考方案3】:

您不能仅使用字典和平面(单级)JSON 来做到这一点。

字典本质上是无序的,在 JSON 和 Swift(以及任何其他语言)中都是如此。如果你需要维护一个顺序,你应该使用一个数组。

很难对您的问题给出具体答案,因为您没有提供任何要保持此顺序的原因,也没有提供有关数据生成方式的详细信息(例如,字典是否总是有相同的键,它们应该始终保持相同的顺序吗?)。

但是,如果确实需要维护秩序,并且您可以使用不同的 JSON 格式,您可以根据您的要求通过以下两种方法之一来实现:

    如果键总是相同且顺序相同...

从数组而非原始字典中填充 JSON。由于您知道元素的顺序,因此您无需任何键就知道哪个元素是哪个。

    如果键不总是相同,或者不总是以相同的顺序...

分别维护一个有序键的数组,以及字典,然后使用该数组以与键在数组中存储相同的顺序访问字典值。

根据您的要求,您可能需要将数组也存储在 JSON 中(例如,与您的字典组合成父字典)。

这可能有点笨拙,但要获得更好的答案,您可能需要提供更多关于您的实际要求的信息。

【讨论】:

以上是关于将 NSDictionary 转换为 Json String 会导致元素重新排序的主要内容,如果未能解决你的问题,请参考以下文章

无法将 NSDictionary 值转换为 json

Obj-C:将 NSDictionary 转换为 JSON 时应用程序崩溃

使用 Swift 将 JSON 字符串转换为 NSDictionary

将包含 NSArray 的 NSDictionary 转换为 JSON

将 NSDictionary 转换为 Json String 会导致元素重新排序

将 JSON 数据从 NSData 转换为 NSDictionary