 
 extension Node {
     public func extract<T : NodeInitializable>(
-        _ keyType: PathIndex...)
-        throws -> T {
-            let node = self[keyType] ?? .null
+        _ path: PathIndex...)
+        throws -> T {
+            return try extract(path: path)
+    }
+
+    public func extract<T : NodeInitializable>(
+        path: [PathIndex])
+        throws -> T {
+            let node = self[path] ?? .null
             return try T(node: node)
     }
 
     public func extract<T : NodeInitializable>(
-        _ keyType: PathIndex...)
+        _ path: PathIndex...)
         throws -> [T] {
-            let node = self[keyType] ?? .null
+            return try extract(path: path)
+    }
+
+    public func extract<T : NodeInitializable>(
+        path: [PathIndex])
+        throws -> [T] {
+            let node = self[path] ?? .null
             return try [T](node: node)
     }
 
     public func extract<T : NodeInitializable>(
-        _ keyType: PathIndex...)
+        _ path: PathIndex...)
         throws -> [[T]] {
-            let initial = self[keyType] ?? .null
+            return try extract(path: path)
+    }
+
+    public func extract<T : NodeInitializable>(
+        path: [PathIndex])
+        throws -> [[T]] {
+            let initial = self[path] ?? .null
             let array = initial.nodeArray ?? [initial]
             return try array.map { try [T](node: $0) }
     }
 
     public func extract<T : NodeInitializable>(
-        _ keyType: PathIndex...)
+        _ path: PathIndex...)
         throws -> [String : T] {
-            guard let object = self[keyType]?.nodeObject else {
+            return try extract(path: path)
+    }
+
+    public func extract<T : NodeInitializable>(
+        path: [PathIndex])
+        throws -> [String : T] {
+            guard let object = self[path]?.nodeObject else {
                 throw NodeError.unableToConvert(node: .null, expected: "\([String: T].self)")
             }
 


extension Node {
    public func extract<T, InputType: NodeInitializable>(
        _ keyType: PathIndex...,
        transform: (InputType) throws -> T)
        throws -> T {
            let node = self[keyType] ?? .null
            let input = try InputType(node: node)
            return try transform(input)
    }

    public func extract<T, InputType: NodeInitializable>(
        _ keyType: PathIndex...,
        transform: (InputType?) throws -> T)
        throws -> T {
            let value = try self[keyType].flatMap { try InputType(node: $0) }
            return try transform(value)
    }
}

    }

    public func extract<T : NodeInitializable>(
        _ path: PathIndex...)
        throws -> [String : [T]] {
            return try extract(path: path)
    }

    public func extract<T : NodeInitializable>(
        path: [PathIndex])
        throws -> [String : [T]] {
            guard let object = self[path]?.nodeObject else {
                throw NodeError.unableToConvert(node: .null, expected: "\([String: [T]].self)")
            }
            return try object.mapValues { return try [T](node: $0) }
    }

    public func extract<T : NodeInitializable>(
        _ path: PathIndex...)
        throws -> Set<T> {
            return try extract(path: path)
    }

    public func extract<T : NodeInitializable>(
        path: [PathIndex])
        throws -> Set<T> {
            let node = self[path] ?? .null
            let array = try [T](node: node)
            return Set(array)
    }
