         }
     }
 
-    fileprivate func box<T : Encodable>(_ value: T) throws -> NSObject {
+    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.
+            if self.storage.count > depth {
+                let _ = self.storage.popContainer()
+            }
+
+            throw error
+        }
+
+        // The top container should be a new container.
+        guard self.storage.count > depth else {
+            return nil
+        }
+
+        return self.storage.popContainer()
+    }
+
+    fileprivate func box(_ value: Encodable) throws -> NSObject {
         return try self.box_(value) ?? NSDictionary()
     }
 
     // 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_<T : Encodable>(_ value: T) throws -> NSObject? {
+    fileprivate func box_(_ value: Encodable) throws -> NSObject? {
+        let type = Swift.type(of: value)
         #if DEPLOYMENT_RUNTIME_SWIFT
-        if T.self == Date.self {
+        if type == Date.self {
             // Respect Date encoding strategy
             return try self.box((value as! Date))
-        } else if T.self == Data.self {
+        } else if type == Data.self {
             // Respect Data encoding strategy
             return try self.box((value as! Data))
-        } else if T.self == URL.self {
+        } else if type == URL.self {
             // Encode URLs as single strings.
             return self.box((value as! URL).absoluteString)
-        } else if T.self == Decimal.self {
+        } else if type == Decimal.self {
             // JSONSerialization can consume NSDecimalNumber values.
             return NSDecimalNumber(decimal: value as! Decimal)
+        } else if value is _JSONStringDictionaryEncodableMarker {
+            return try box(value as! [String : Encodable])
         }
         
         #else
-        if T.self == Date.self || T.self == NSDate.self {
+        if type == Date.self || type == NSDate.self {
             // Respect Date encoding strategy
             return try self.box((value as! Date))
-        } else if T.self == Data.self || T.self == NSData.self {
+        } else if type == Data.self || type == NSData.self {
             // Respect Data encoding strategy
             return try self.box((value as! Data))
-        } else if T.self == URL.self || T.self == NSURL.self {
+        } else if type == URL.self || type == NSURL.self {
             // Encode URLs as single strings.
             return self.box((value as! URL).absoluteString)
-        } else if T.self == Decimal.self {
+        } else if type == Decimal.self {
             // JSONSerialization can consume NSDecimalNumber values.
             return NSDecimalNumber(decimal: value as! Decimal)
+        } else if value is _JSONStringDictionaryEncodableMarker {
+            return try box(value as! [String : Encodable])
         }
         #endif
         

                                                                        debugDescription: "Invalid URL string."))
            }
            
            return (url as! T)
        } else if type == Decimal.self || type == NSDecimalNumber.self {
            return try self.unbox(value, as: Decimal.self) as? T
        } else {
            self.storage.push(container: value)
            defer { self.storage.popContainer() }
            return try type.init(from: self)
        }
        #endif
        
        return decoded
    }
}


        }
    }

    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 (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_(value, as: elementType)
        }

        return result as? T
    }

    fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
        return try unbox_(value, as: type) as? T
    }

    fileprivate func unbox_(_ value: Any, as type: Decodable.Type) throws -> Any? {
        #if DEPLOYMENT_RUNTIME_SWIFT
        // Bridging differences require us to split implementations here
        if type == Date.self {
            guard let date = try self.unbox(value, as: Date.self) else { return nil }
            return date
        } else if type == Data.self {
            guard let data = try self.unbox(value, as: Data.self) else { return nil }
            return data
        } else if type == URL.self {
            guard let urlString = try self.unbox(value, as: String.self) else {
                return nil
            }
