Skip to content

Commit 222fab8

Browse files
committed
Final fixes
1 parent 884cd69 commit 222fab8

File tree

3 files changed

+33
-14
lines changed

3 files changed

+33
-14
lines changed

Sources/Foundation/JSONSerialization+Parser.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ internal struct JSONParser {
128128
// consume the comma
129129
reader.moveReaderIndex(forwardBy: 1)
130130
// consume the whitespace before the next value
131-
try reader.consumeWhitespace()
131+
if try reader.consumeWhitespace() == ._closebracket {
132+
// the foundation json implementation does support trailing commas
133+
reader.moveReaderIndex(forwardBy: 1)
134+
return array
135+
}
132136
continue
133137
default:
134138
throw JSONError.unexpectedCharacter(ascii: ascii, characterIndex: reader.readerIndex)
@@ -178,7 +182,11 @@ internal struct JSONParser {
178182
return object
179183
case ._comma:
180184
reader.moveReaderIndex(forwardBy: 1)
181-
try reader.consumeWhitespace()
185+
if try reader.consumeWhitespace() == ._closebrace {
186+
// the foundation json implementation does support trailing commas
187+
reader.moveReaderIndex(forwardBy: 1)
188+
return object
189+
}
182190
continue
183191
default:
184192
throw JSONError.unexpectedCharacter(ascii: commaOrBrace, characterIndex: reader.readerIndex)
@@ -637,6 +645,7 @@ extension UInt8 {
637645

638646

639647
enum JSONError: Swift.Error, Equatable {
648+
case cannotConvertInputDataToUTF8
640649
case unexpectedCharacter(ascii: UInt8, characterIndex: Int)
641650
case unexpectedEndOfFile
642651
case tooManyNestedArraysOrDictionaries(characterIndex: Int)

Sources/Foundation/JSONSerialization.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,18 @@ open class JSONSerialization : NSObject {
185185
do {
186186
let jsonValue = try data.withUnsafeBytes { (ptr) -> JSONValue in
187187
let (encoding, advanceBy) = JSONSerialization.detectEncoding(ptr)
188-
guard encoding == .utf8, advanceBy == 0 else {
189-
let newPtr = ptr[advanceBy..<ptr.count]
190-
let json = String(bytes: newPtr, encoding: encoding)!
191-
return try json.utf8.withContiguousStorageIfAvailable { (utf8) -> JSONValue in
192-
var parser = JSONParser(bytes: Array(utf8))
193-
return try parser.parse()
194-
}!
188+
189+
if encoding == .utf8 {
190+
// we got utf8... happy path
191+
var parser = JSONParser(bytes: Array(ptr[advanceBy..<ptr.count]))
192+
return try parser.parse()
195193
}
196-
197-
var parser = JSONParser(bytes: Array(ptr))
194+
195+
guard let utf8String = String(bytes: ptr[advanceBy..<ptr.count], encoding: encoding) else {
196+
throw JSONError.cannotConvertInputDataToUTF8
197+
}
198+
199+
var parser = JSONParser(bytes: Array(utf8String.utf8))
198200
return try parser.parse()
199201
}
200202

@@ -205,6 +207,10 @@ open class JSONSerialization : NSObject {
205207
return try jsonValue.toObjcRepresentation(options: opt)
206208
} catch let error as JSONError {
207209
switch error {
210+
case .cannotConvertInputDataToUTF8:
211+
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: [
212+
NSDebugDescriptionErrorKey : "Cannot convert input string to valid utf8 input."
213+
])
208214
case .unexpectedEndOfFile:
209215
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: [
210216
NSDebugDescriptionErrorKey : "Unexpected end of file during JSON parse."

Tests/Foundation/Tests/TestJSONSerialization.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,9 +623,13 @@ extension TestJSONSerialization {
623623
let subject = "[1.1e547]"
624624
let data = Data(subject.utf8)
625625

626-
var numbers: [NSNumber]?
627-
XCTAssertNoThrow(numbers = try getjsonObjectResult(data, objectType) as? [NSNumber])
628-
XCTAssertEqual(numbers?.first?.doubleValue.isInfinite, true)
626+
XCTAssertThrowsError(try getjsonObjectResult(data, objectType)) { error in
627+
guard let nserror = (error as? NSError) else {
628+
return XCTFail("Unexpected error: \(error)")
629+
}
630+
XCTAssertEqual(nserror.domain, NSCocoaErrorDomain)
631+
XCTAssertEqual(CocoaError(_nsError: nserror).code, .propertyListReadCorrupt)
632+
}
629633
}
630634

631635
func deserialize_numbers_as_reference_types(objectType: ObjectType) {

0 commit comments

Comments
 (0)