Skip to content

Commit

Permalink
Merge pull request #4757 from woxtu/sorted-keys
Browse files Browse the repository at this point in the history
Fix `JSONEncoder.OutputFormatting.sortedKeys` behavior
  • Loading branch information
YOCKOW authored Dec 12, 2023
2 parents 9f011c6 + d62fc6d commit 1b514e4
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Sources/Foundation/JSONEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ extension JSONValue {
bytes.append(._closebracket)
case .object(let dict):
if #available(macOS 10.13, *), options.contains(.sortedKeys) {
let sorted = dict.sorted { $0.key < $1.key }
let sorted = dict.sorted { $0.key.compare($1.key, options: [.caseInsensitive, .diacriticInsensitive, .forcedOrdering, .numeric, .widthInsensitive]) == .orderedAscending }
self.writeObject(sorted, into: &bytes)
} else {
self.writeObject(dict, into: &bytes)
Expand Down Expand Up @@ -1073,7 +1073,7 @@ extension JSONValue {
bytes.append(._closebracket)
case .object(let dict):
if #available(macOS 10.13, *), options.contains(.sortedKeys) {
let sorted = dict.sorted { $0.key < $1.key }
let sorted = dict.sorted { $0.key.compare($1.key, options: [.caseInsensitive, .diacriticInsensitive, .forcedOrdering, .numeric, .widthInsensitive]) == .orderedAscending }
self.writePrettyObject(sorted, into: &bytes, depth: depth)
} else {
self.writePrettyObject(dict, into: &bytes, depth: depth)
Expand Down
66 changes: 56 additions & 10 deletions Tests/Foundation/Tests/TestJSONEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,27 +235,73 @@ class TestJSONEncoder : XCTestCase {
""")
}

func test_encodingOutputFormattingSortedKeys() {
let expectedJSON = "{\"email\":\"[email protected]\",\"name\":\"Johnny Appleseed\"}".data(using: .utf8)!
let person = Person.testValue
func test_encodingOutputFormattingSortedKeys() throws {
let expectedJSON = try XCTUnwrap("""
{"2":"2","7":"7","25":"25","alice":"alice","bob":"bob","Charlie":"Charlie","中国":"中国","日本":"日本","韓国":"韓国"}
""".data(using: .utf8))
let testValue = [
"2": "2",
"25": "25",
"7": "7",
"alice": "alice",
"bob": "bob",
"Charlie": "Charlie",
"日本": "日本",
"中国": "中国",
"韓国": "韓国",
]
#if os(macOS) || DARWIN_COMPATIBILITY_TESTS
if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys])
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
let payload = try encoder.encode(testValue)
XCTAssertEqual(expectedJSON, payload)
}
#else
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.sortedKeys])
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
let payload = try encoder.encode(testValue)
XCTAssertEqual(expectedJSON, payload)
#endif
}

func test_encodingOutputFormattingPrettyPrintedSortedKeys() {
let expectedJSON = "{\n \"email\" : \"[email protected]\",\n \"name\" : \"Johnny Appleseed\"\n}".data(using: .utf8)!
let person = Person.testValue
func test_encodingOutputFormattingPrettyPrintedSortedKeys() throws {
let expectedJSON = try XCTUnwrap("""
{
"2" : "2",
"7" : "7",
"25" : "25",
"alice" : "alice",
"bob" : "bob",
"Charlie" : "Charlie",
"中国" : "中国",
"日本" : "日本",
"韓国" : "韓国"
}
""".data(using: .utf8))
let testValue = [
"2": "2",
"25": "25",
"7": "7",
"alice": "alice",
"bob": "bob",
"Charlie": "Charlie",
"日本": "日本",
"中国": "中国",
"韓国": "韓国",
]
#if os(macOS) || DARWIN_COMPATIBILITY_TESTS
if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.prettyPrinted, .sortedKeys])
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let payload = try encoder.encode(testValue)
XCTAssertEqual(expectedJSON, payload)
}
#else
_testRoundTrip(of: person, expectedJSON: expectedJSON, outputFormatting: [.prettyPrinted, .sortedKeys])
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let payload = try encoder.encode(testValue)
XCTAssertEqual(expectedJSON, payload)
#endif
}

Expand Down

0 comments on commit 1b514e4

Please sign in to comment.