   case StructErrors(type: String, errors: [String: JsonDecodeError])
 }
 
-// Decode function for JsonObject.
-// Would be nicer as an extension method.
-public func JsonObject_decodeJson(json: AnyObject) throws -> JsonObject {
-  guard let result = json as? JsonObject else {
-    throw JsonDecodeError.WrongType(rawValue: json, expectedType: "JsonObject")
-  }
-
-  return result
+class JsonDecoder {
+  var errors: [String: JsonDecodeError] = [:]
+  let dict: [String : AnyObject]
+
+  init(json: AnyObject) throws {
+
+    guard let dict = json as? [String : AnyObject] else {
+      self.dict = [:] // Init field, for Swift 2.0
+      throw JsonDecodeError.WrongType(rawValue: json, expectedType: "Object")
+    }
+
+    self.dict = dict
+  }
+
+  func decode<T>(name: String, decoder: AnyObject throws -> T) throws -> T? {
+
+    if let field: AnyObject = dict[name] {
+      do {
+        return try decoder(field)
+      }
+      catch let error as JsonDecodeError {
+        errors[name] = error
+      }
+    }
+    else {
+      errors[name] = JsonDecodeError.MissingField
+    }
+
+    return nil
+  }
+
+  func decode<T>(name: String, decoder: AnyObject throws -> T?) throws -> T?? {
+
+    if let field: AnyObject = dict[name] where !(field is NSNull) {
+      do {
+        return try decoder(field)
+      }
+      catch let error as JsonDecodeError {
+        errors[name] = error
+      }
+    }
+    else {
+      return .Some(nil)
+    }
+
+    return nil
+  }
+}
+
+extension SequenceType where Generator.Element == (String, AnyObject) {
+  public static func decodeJson(json: AnyObject) throws -> JsonObject {
+    guard let result = json as? JsonObject else {
+      throw JsonDecodeError.WrongType(rawValue: json, expectedType: "JsonObject")
+    }
+
+    return result
+  }
 }
 
 extension String {

}

extension Dictionary {
  public static func decodeJson(decodeKey: AnyObject throws -> Key, _ decodeValue: AnyObject throws -> Value, _ json: AnyObject) throws -> [Key: Value] {

    guard let dict = json as? [Key: AnyObject] else {
      throw JsonDecodeError.WrongType(rawValue: json, expectedType: "Dictionary")
    }

    var errors: [String: JsonDecodeError] = [:]
    var result: [Key: Value] = [:]

    for (key, val) in dict {
      do {
        result[key] = try decodeValue(val)
      }
      catch let error as JsonDecodeError {
        errors["\(key)"] = error
      }
    }

    if errors.count > 0 {
      throw JsonDecodeError.DictionaryErrors(errors)
    }

    return result
  }

  public func encodeJson(encodeJsonKey: Key -> String, _ encodeJsonValue: Value -> AnyObject) -> [String: AnyObject] {

}

extension Optional {
  public static func decodeJson(decodeWrapped: AnyObject throws -> Wrapped) -> AnyObject throws -> Wrapped? {
    return { json in
      do {
        return try decodeWrapped(json)
      }
      catch let error as JsonDecodeError {
        if case let .WrongType(rawValue: rawValue, expectedType: expectedType) = error {
          throw JsonDecodeError.WrongType(rawValue: rawValue, expectedType: "\(expectedType)?")
        }

        throw error
      }
    }
  }

