Repository: Moya/Moya
File: Sources/Moya/Response.swift (Swift)

Code before:
            // Key path was provided, try to parse string at key path
            guard let jsonDictionary = try mapJSON() as? NSDictionary,
                let string = jsonDictionary.value(forKeyPath:keyPath) as? String else {
                    throw MoyaError.stringMapping(self)
            }
            return string
        } else {
            // Key path was not provided, parse entire response as string
            guard let string = String(data: data, encoding: .utf8) else {
                throw MoyaError.stringMapping(self)
            }
            return string
        }
    }

    /// Maps data received from the signal into a Decodable object.
    ///
    /// - parameter atKeyPath: Optional key path at which to parse object.
    /// - parameter using: A `JSONDecoder` instance which is used to decode data to an object.
    func map<D: Decodable>(_ type: D.Type, atKeyPath keyPath: String? = nil, using decoder: JSONDecoder = JSONDecoder()) throws -> D {
        let jsonData: Data
        if let keyPath = keyPath {
            guard let jsonDictionary = (try mapJSON() as? NSDictionary)?.value(forKeyPath: keyPath) as? [String: Any] else {
                throw MoyaError.jsonMapping(self)
            }
            jsonData = try JSONSerialization.data(withJSONObject: jsonDictionary, options: [])
        } else {
            jsonData = data
        }
        do {
            return try decoder.decode(D.self, from: jsonData)
        } catch let error {
            throw MoyaError.objectMapping(error, self)
        }
    }
}


Review comment (bug):
don't we wanna catch the error here as well and make it a `.jsonMapping` as well? 🤔 

Code after:
            // Key path was provided, try to parse string at key path
            guard let jsonDictionary = try mapJSON() as? NSDictionary,
                let string = jsonDictionary.value(forKeyPath:keyPath) as? String else {
                    throw MoyaError.stringMapping(self)
            }
            return string
        } else {
            // Key path was not provided, parse entire response as string
            guard let string = String(data: data, encoding: .utf8) else {
                throw MoyaError.stringMapping(self)
            }
            return string
        }
    }

    /// Maps data received from the signal into a Decodable object.
    ///
    /// - parameter atKeyPath: Optional key path at which to parse object.
    /// - parameter using: A `JSONDecoder` instance which is used to decode data to an object.
    func map<D: Decodable>(_ type: D.Type, atKeyPath keyPath: String? = nil, using decoder: JSONDecoder = JSONDecoder()) throws -> D {
        let jsonData: Data
        if let keyPath = keyPath {
            guard let jsonDictionary = (try mapJSON() as? NSDictionary)?.value(forKeyPath: keyPath) as? [String: Any] else {
                throw MoyaError.jsonMapping(self)
            }
            do {
                jsonData = try JSONSerialization.data(withJSONObject: jsonDictionary, options: [])
            } catch {
                throw MoyaError.jsonMapping(self)
            }
        } else {
            jsonData = data
        }
        do {
            return try decoder.decode(D.self, from: jsonData)
        } catch let error {
            throw MoyaError.objectMapping(error, self)
        }
    }
}