Skip to content

Add compatibility path for JSONEncoder.sortedKeys behavior change #631

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

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions Sources/FoundationEssentials/JSON/JSONWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -347,11 +347,36 @@ internal struct JSONWriter {
}

if sortedKeys {
let elems = dict.sorted { a, b in
a.key.utf8.lexicographicallyPrecedes(b.key.utf8)
#if FOUNDATION_FRAMEWORK
var compatibilitySorted = false
if JSONEncoder.compatibility1 {
// If applicable, use the old NSString-based sorting with appropriate options
compatibilitySorted = true
let nsKeysAndValues = dict.map {
(key: $0.key as NSString, value: $0.value)
}
let elems = nsKeysAndValues.sorted(by: { a, b in
let options: String.CompareOptions = [.numeric, .caseInsensitive, .forcedOrdering]
let range = NSMakeRange(0, a.key.length)
let locale = Locale.system
return a.key.compare(b.key as String, options: options, range: range, locale: locale) == .orderedAscending
})
for elem in elems {
try serializeObjectElement(key: elem.key as String, value: elem.value, depth: depth)
}
}
for elem in elems {
try serializeObjectElement(key: elem.key as String, value: elem.value, depth: depth)
#else
let compatibilitySorted = false
#endif

// If we didn't use the NSString-based compatibility sorting, sort lexicographically by the UTF-8 view
if !compatibilitySorted {
let elems = dict.sorted { a, b in
a.key.utf8.lexicographicallyPrecedes(b.key.utf8)
}
for elem in elems {
try serializeObjectElement(key: elem.key as String, value: elem.value, depth: depth)
}
}
} else {
for (key, value) in dict {
Expand Down