Skip to content

Commit 1b514e4

Browse files
authored
Merge pull request #4757 from woxtu/sorted-keys
Fix `JSONEncoder.OutputFormatting.sortedKeys` behavior
2 parents 9f011c6 + d62fc6d commit 1b514e4

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

Sources/Foundation/JSONEncoder.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ extension JSONValue {
10111011
bytes.append(._closebracket)
10121012
case .object(let dict):
10131013
if #available(macOS 10.13, *), options.contains(.sortedKeys) {
1014-
let sorted = dict.sorted { $0.key < $1.key }
1014+
let sorted = dict.sorted { $0.key.compare($1.key, options: [.caseInsensitive, .diacriticInsensitive, .forcedOrdering, .numeric, .widthInsensitive]) == .orderedAscending }
10151015
self.writeObject(sorted, into: &bytes)
10161016
} else {
10171017
self.writeObject(dict, into: &bytes)
@@ -1073,7 +1073,7 @@ extension JSONValue {
10731073
bytes.append(._closebracket)
10741074
case .object(let dict):
10751075
if #available(macOS 10.13, *), options.contains(.sortedKeys) {
1076-
let sorted = dict.sorted { $0.key < $1.key }
1076+
let sorted = dict.sorted { $0.key.compare($1.key, options: [.caseInsensitive, .diacriticInsensitive, .forcedOrdering, .numeric, .widthInsensitive]) == .orderedAscending }
10771077
self.writePrettyObject(sorted, into: &bytes, depth: depth)
10781078
} else {
10791079
self.writePrettyObject(dict, into: &bytes, depth: depth)

Tests/Foundation/Tests/TestJSONEncoder.swift

+56-10
Original file line numberDiff line numberDiff line change
@@ -235,27 +235,73 @@ class TestJSONEncoder : XCTestCase {
235235
""")
236236
}
237237

238-
func test_encodingOutputFormattingSortedKeys() {
239-
let expectedJSON = "{\"email\":\"[email protected]\",\"name\":\"Johnny Appleseed\"}".data(using: .utf8)!
240-
let person = Person.testValue
238+
func test_encodingOutputFormattingSortedKeys() throws {
239+
let expectedJSON = try XCTUnwrap("""
240+
{"2":"2","7":"7","25":"25","alice":"alice","bob":"bob","Charlie":"Charlie","中国":"中国","日本":"日本","韓国":"韓国"}
241+
""".data(using: .utf8))
242+
let testValue = [
243+
"2": "2",
244+
"25": "25",
245+
"7": "7",
246+
"alice": "alice",
247+
"bob": "bob",
248+
"Charlie": "Charlie",
249+
"日本": "日本",
250+
"中国": "中国",
251+
"韓国": "韓国",
252+
]
241253
#if os(macOS) || DARWIN_COMPATIBILITY_TESTS
242254
if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
243-
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys])
255+
let encoder = JSONEncoder()
256+
encoder.outputFormatting = .sortedKeys
257+
let payload = try encoder.encode(testValue)
258+
XCTAssertEqual(expectedJSON, payload)
244259
}
245260
#else
246-
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys])
261+
let encoder = JSONEncoder()
262+
encoder.outputFormatting = .sortedKeys
263+
let payload = try encoder.encode(testValue)
264+
XCTAssertEqual(expectedJSON, payload)
247265
#endif
248266
}
249267

250-
func test_encodingOutputFormattingPrettyPrintedSortedKeys() {
251-
let expectedJSON = "{\n \"email\" : \"[email protected]\",\n \"name\" : \"Johnny Appleseed\"\n}".data(using: .utf8)!
252-
let person = Person.testValue
268+
func test_encodingOutputFormattingPrettyPrintedSortedKeys() throws {
269+
let expectedJSON = try XCTUnwrap("""
270+
{
271+
"2" : "2",
272+
"7" : "7",
273+
"25" : "25",
274+
"alice" : "alice",
275+
"bob" : "bob",
276+
"Charlie" : "Charlie",
277+
"中国" : "中国",
278+
"日本" : "日本",
279+
"韓国" : "韓国"
280+
}
281+
""".data(using: .utf8))
282+
let testValue = [
283+
"2": "2",
284+
"25": "25",
285+
"7": "7",
286+
"alice": "alice",
287+
"bob": "bob",
288+
"Charlie": "Charlie",
289+
"日本": "日本",
290+
"中国": "中国",
291+
"韓国": "韓国",
292+
]
253293
#if os(macOS) || DARWIN_COMPATIBILITY_TESTS
254294
if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
255-
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.prettyPrinted, .sortedKeys])
295+
let encoder = JSONEncoder()
296+
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
297+
let payload = try encoder.encode(testValue)
298+
XCTAssertEqual(expectedJSON, payload)
256299
}
257300
#else
258-
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.prettyPrinted, .sortedKeys])
301+
let encoder = JSONEncoder()
302+
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
303+
let payload = try encoder.encode(testValue)
304+
XCTAssertEqual(expectedJSON, payload)
259305
#endif
260306
}
261307

0 commit comments

Comments
 (0)