import Foundation public protocol AnyDecoder { func decode(_ type: T.Type, from data: Data) throws -> T } extension JSONDecoder: AnyDecoder {} extension PropertyListDecoder: AnyDecoder {} extension Data { public func decode(using decoder: AnyDecoder = JSONDecoder()) throws -> T { return try decoder.decode(T.self, from: self) } } extension KeyedDecodingContainerProtocol { public func decode(forKey key: Key) throws -> T { return try decode(T.self, forKey: key) } public func decode( forKey key: Key, default defaultExpression: @autoclosure () -> T ) throws -> T { return try decodeIfPresent(T.self, forKey: key) ?? defaultExpression() } } extension Decodable { public static func decode(fileName: String, bundle: Bundle = Bundle.main) throws -> Self{ guard let path = bundle.path(forResource: fileName, ofType: ".json") else { throw JSONError.pathNotFound } guard let jsonData = try? Data(contentsOf: URL(fileURLWithPath: path)) else { throw JSONError.data(path: path) } do { return try jsonData.decode() } catch { throw JSONError.other(error: error) } } }