Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-5698] .sortedKeys appears to ignore .numeric option #4082

Closed
swift-ci opened this issue Aug 16, 2017 · 4 comments
Closed

[SR-5698] .sortedKeys appears to ignore .numeric option #4082

swift-ci opened this issue Aug 16, 2017 · 4 comments

Comments

@swift-ci
Copy link
Contributor

Previous ID SR-5698
Radar None
Original Reporter danbarychev (JIRA User)
Type Bug
Status Resolved
Resolution Invalid

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug, Linux
Assignee None
Priority Medium

md5: db8160e82be8474efdf89e355ba18938

Issue Description:

I'm working on a project that involves cryptographic signature verification on JSON files, but I'm experiencing some issues trying to get JSON files sorted as I need them. I need the JSON files to have all keys be sorted both alphabetically and numerically so I'm using the .sortedKeys option in JSONSerialization to do this. I am able to sort all keys alphabetically but not numerically although I believe that .sortedKeys should do both. I'm basing my judgement off of the following implementation at https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/JSONSerialization.swift#L531-L546

if sortedKeys {
let elems = try dict.sorted(by: { a, b in
guard let a = a.key as? String,
let b = b.key as? String else {
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
}
let options: NSString.CompareOptions = [.numeric, .caseInsensitive, .forcedOrdering]
let range: Range<String.Index> = a.startIndex..<a.endIndex
let locale = NSLocale.system
return a.compare(b, options: options, range: range, locale: locale) == .orderedAscending
})
for elem in elems {
try serializeDictionaryElement(key: elem.key, value: elem.value)
}
}

Since this implementation uses the .numeric option, I would assume that .sortedKeys should sort keys numerically although it doesn't appear to do so.

Here is an example

This is how I call .sortedKeys

guard let roleJSONData = try JSONSerialization.jsonObject(with: roleData) as? [String: Any],
      let roleSignedJSONData = roleJSONData["signed"] as? NSDictionary
            else {
              return roleSignedData
        }
        
roleSignedData = try JSONSerialization.data(withJSONObject: roleSignedJSONData, options: .sortedKeys)

I need to achieve the following sorting:

{"0501a2a51fa40da53ad9739e95456859fb81d4c5bce9c4b831149eb37817a5e5":.....,
"1b729c9ed9df962ac85c78742f973b5a63613693d093898dc5b6fae811f3e583":.....,
"f06bda5d2b6ec003e9b3458a45be4e9be79b67d3b34c572dfd8f89c8a0c85ef3":.....,
"fbac760dc452bbdce483c042dbed72b4fb1e892dc46a6717544e4f55560b7d22":.....}

But .sortedKeys gives me this sorting:

{"1b729c9ed9df962ac85c78742f973b5a63613693d093898dc5b6fae811f3e583":.....,
"0501a2a51fa40da53ad9739e95456859fb81d4c5bce9c4b831149eb37817a5e5":.....,
"f06bda5d2b6ec003e9b3458a45be4e9be79b67d3b34c572dfd8f89c8a0c85ef3":.....,
"fbac760dc452bbdce483c042dbed72b4fb1e892dc46a6717544e4f55560b7d22":.....}

*I have taken these two examples from the signed_root.json and the extracted_signed_root.json files that I have attached to this issue

I was wondering if there's a chance that the .sortedKeys I'm using is not what I see in the implementation or if there may be a bug of some kind where .sortedKeys doesn't sort numerically. Any clarification would be greatly appreciated.

@belkadan
Copy link

@itaiferber?

@itaiferber
Copy link
Contributor

Looks like a swift-corelibs-foundation issue. You can see from the linked JSONSerialization code that we do supply the .numeric option, but it looks like it might not be respected. Going to take a look.

@itaiferber
Copy link
Contributor

Scratch that, this behaves correctly. Numeric search is being respected — it so happens that 0501a2a51fa40da53ad9739e95456859fb81d4c5bce9c4b831149eb37817a5e5 begins with the number 0501 (501), while 1b729c9ed9df962ac85c78742f973b5a63613693d093898dc5b6fae811f3e583 starts with the number 1. Since 1 < 501, it's being sorted to the front. The numeric sorting is correct here; it's just that seeing the leading 0 can be misleading.

@swift-ci
Copy link
Contributor Author

Comment by Daniel Barychev (JIRA)

@itaiferber That clears things up, thank you!

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants