         return Date(timeIntervalSince1970: TimeInterval(timestamp))
     }
 }
+
+/// A result enum with two cases: 'success' or 'failure'
+/// The success case provides the result as associated value
+/// The failure case provides an error as associated value
+public enum DTOResult<T, E: Error>{
+    case success(T)
+    case failure(E)
+    
+    func flatMap<P>(_ f:(T) -> DTOResult<P, NSError>) -> DTOResult<P, NSError> {
+        switch self {
+        case .success(let value):
+            return f(value)
+        case .failure(let error):
+            return DTOResult<P, NSError>.failure(error as NSError)
+        }
+    }
+}
+
+
+/// Helper struct to parse input to DTO object of array of DTO objects
+/// Input can be either Data or String or [String: Any] or [Any]
+/// Thus you can parse a network response (data or string), a json string
+/// or any Dictionary ([String: Any]) or any Array
+public struct DTOParser {
+    
+    
+    /// Parse a single DTO Object
+    ///
+    /// - Parameter data: Data, String, Dictionary or Array
+    /// - Returns: a DTOResult object with either the result or the error as associated value
+    public func parse<T: JSOBJSerializable>(_ data: Any) -> DTOResult<T, NSError> {
+        let decodedData = decodeData(data)
+        return decodedData.flatMap({ (obj: Any) -> DTOResult<T, NSError> in
+            guard let dto = T(jsonData: obj as? JSOBJ) else {
+                return .failure(createError(with: -19, message: "Object not mappable"))
+            }
+            return .success(dto)
+        })
+    }
+    
+    /// Parse an array of DTO objects
+    ///
+    /// - Parameter data: Data, String, Dictionary or Array
+    /// - Returns: a DTOResult object with either the result or the error as associated value
+    public func parse<T: JSOBJSerializable>(_ data: Any) -> DTOResult<T, NSError> {
+        let decodedData = decodeData(data)
+        return decodedData.flatMap({ (obj: Any) -> DTOResult<[T], NSError> in
+            guard let array = obj as? [Any] else {
+                return .failure(createError(with: -19, message: "Object not mappable"))
+            }
+            return arrayToModels(array)
+        })
+    }
+    
+    //MARK: - Private interface
+    
+    private func arrayToModels<T: JSOBJSerializable>(_ objects: [Any]) -> DTOResult<[T], NSError> {
+        let rslt = objects.flatMap { T(jsonData: $0 as? JSOBJ) }
+        return .success(rslt)
+    }
+    
+    private func decodeData(_ input: Any) -> DTOResult<Any, NSError> {
+        if let dict = input as? [String: Any] { return .success(dict) }
+        if let arr = input as? [Any] { return .success(arr) }
+        let data = input as? Data ?? (input as? String)?.data(using: .utf8)
+        
+        let defaultError = createError(with: -18, message: "No vaid data to decode to JSON!")
+        
+        if data == nil { return .failure(defaultError) }
+        do {
+            let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions())
+            return .success(json)
+        }
+        catch let error {
+            return .failure(error as NSError)
+        }
+    }
+    
+    private func createError(with code: Int, message: String) -> NSError {
+        return NSError(domain: "com.farbflash.DTOParser", code: code, userInfo: [NSLocalizedDescriptionKey: message])
+    }
+}
+

        if let intVal = Int(inputString) { return dateFromLong(intVal) }
        return nil
    }

    private func dateFromDouble(_ timestamp: Double?) -> Date? {
        guard let timestamp = timestamp else {
            return nil
        }
        return Date(timeIntervalSince1970: (timestamp/1000.0))
    }

    private func dateFromLong(_ timestamp: Int?) -> Date? {
        guard let timestamp = timestamp else {
            return nil

        if let val = jsonObject as? Double { return String(describing: val) }
        return nil
    }
    
    /**
     Try to convert a string representing a date to a NSDate object
     
     Start with ISO 8601 format, then our "Conrad German date format", then a timestamp
     
     - parameter dateString: String representing a date in ISO 8601 format
     
     - returns: NSDate object corresponding to input string
     */
    private func dateFromString(_ dateString: String?) -> Date? {
