     }
 
     fileprivate func unbox<T>(_ value: Any, as type: _JSONStringDictionaryDecodableMarker.Type) throws -> T? {
+        guard !(value is NSNull) else { return nil }
+
         var result = [String : Any]()
         guard let dict = value as? NSDictionary else {
             throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
         }
         let elementType = type.elementType
-        for (k, v) in dict {
-            guard let key = k as? String else {
-                throw DecodingError._typeMismatch(at: self.codingPath, expectation: String.self, reality: k)
-            }
+        for (key, value) in dict {
+            let key = key as! String
             self.codingPath.append(_JSONKey(stringValue: key, intValue: nil))
             defer { self.codingPath.removeLast() }
 
-            result[key] = try unbox_(v, as: elementType)
+            result[key] = try unbox_(value, as: elementType)
         }
 
         return result as? T

        }

        return self.storage.popContainer()
    }

    // This method is called "box_" instead of "box" to disambiguate it from the overloads. Because the return type here is different from all of the "box" overloads (and is more general), any "box" calls in here would call back into "box" recursively instead of calling the appropriate overload, which is not what we want.

        }
    }

    fileprivate func box(_ dict: [String : Encodable]) throws -> NSObject? {
        let depth = self.storage.count
        let result = self.storage.pushKeyedContainer()
        do {
            for (key, value) in dict {
                self.codingPath.append(_JSONKey(stringValue: key, intValue: nil))
                defer { self.codingPath.removeLast() }
                result[key] = try box(value)
            }
        } catch {
            // If the value pushed a container before throwing, pop it back off to restore state.
