     /// - Experiment: Note that the return type of this function is different than on Darwin Foundation (Any instead of AnyObject). This is likely to change once we have a more complete story for bridging in place.
     public class func JSONObjectWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> Any {
         
-        guard let string = NSString(data: data, encoding: detectEncoding(data)) else {
-            throw NSError(domain: NSCocoaErrorDomain, code: NSCocoaError.PropertyListReadCorruptError.rawValue, userInfo: [
-                "NSDebugDescription" : "Unable to convert data to a string using the detected encoding. The data may be corrupt."
-            ])
-        }
-        return try JSONObjectWithString(string._swiftObject)
+        let bytes = UnsafePointer<UInt8>(data.bytes)
+        let encoding: NSStringEncoding
+        let buffer: UnsafeBufferPointer<UInt8>
+        if let detected = parseBOM(bytes, length: data.length) {
+            encoding = detected.encoding
+            buffer = UnsafeBufferPointer(start: bytes.advancedBy(detected.skipLength), count: data.length - detected.skipLength)
+        }
+        else {
+            encoding = detectEncoding(bytes, data.length)
+            buffer = UnsafeBufferPointer(start: bytes, count: data.length)
+        }
+
+        let source = JSONReader.UnicodeSource(buffer: buffer, encoding: encoding)
+        let reader = JSONReader(source: source)
+        if let (object, _) = try reader.parseObject(0) {
+            return object
+        }
+        else if let (array, _) = try reader.parseArray(0) {
+            return array
+        }
+        throw NSError(domain: NSCocoaErrorDomain, code: NSCocoaError.PropertyListReadCorruptError.rawValue, userInfo: [
+            "NSDebugDescription" : "JSON text did not start with array or object and option to allow fragments not set."
+        ])
     }
     
     /* Write JSON data into a stream. The stream should be opened and configured. The return value is the number of bytes written to the stream, or 0 on error. All other behavior of this method is the same as the dataWithJSONObject:options:error: method.

// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//


public struct NSJSONReadingOptions : OptionSetType {
    public let rawValue : UInt

        return NSUTF8StringEncoding
    }
    
    static func parseBOM(bytes: UnsafePointer<UInt8>, length: Int) -> (encoding: NSStringEncoding, skipLength: Int)? {
        if length >= 2 {
            switch (bytes[0], bytes[1]) {
            case (0xEF, 0xBB):
                if length >= 3 && bytes[2] == 0xBF {
                    return (NSUTF8StringEncoding, 3)
                }
            case (0x00, 0x00):
                if length >= 4 && bytes[2] == 0xFE && bytes[3] == 0xFF {
                    return (NSUTF32BigEndianStringEncoding, 4)
                }
            case (0xFF, 0xFE):
                if length >= 4 && bytes[2] == 0 && bytes[3] == 0 {
                    return (NSUTF32LittleEndianStringEncoding, 4)
                }
                return (NSUTF16LittleEndianStringEncoding, 2)
            case (0xFE, 0xFF):
                return (NSUTF16BigEndianStringEncoding, 2)
            default:
                break
            }
