parseJSON通用函数怎么写?迅速

问题描述

我的数据模型有不同的结构。 当我想用 JsonDecoder().decode 解析数据时,我需要在 .decoder(SomeType.self,from: data)

中设置一个 .Type.self

我想写一个支持函数,可以分别返回正确的类型。 像这样的东西 但我不知道怎么...

func check<T>(string: String) -> T
if string == "something" {
return Something.type
}

func parseJSON(from data: Data,with address: String)-> Codable? {
let type = check(string: address) 
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(type.self,from: data)
return decodedData
} catch let error {
print(error)
return nil
}
}

当我编写下面的代码时,一切正常。但我总是不得不一遍又一遍地编写几乎没有区别的 parseJSON func

  func fetch(from adress: String) {
        guard let url = URL(string: adress) else {print("can't get URL from current urlAdress"); return}
        let json = makeHttpBody(from: adress)
        let jsonData = try? JSONSerialization.data(withJSONObject: json)
        var request = URLRequest(url: url,cachePolicy: .useProtocolCachePolicy)
        request.httpMethod = K.post
        request.setValue(K.contentType,forHTTPHeaderField:K.applicationjson)
        request.timeoutInterval = Double.infinity
        request.httpBody = jsonData
        
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: request) { (data,responce,error) in
            if error != nil {
                print(error!.localizedDescription)
            }
            if let safeData = data {
            
                if adress == K.balanceUrl {
                if let parsedData = self.parseJsonBalance(from: safeData) {
                    self.delegate?.didUpdateData(with: self,with: parsedData)
                }
                } else if adress == K.projectsUrl {
                    if let parsedData = self.parseJsonProject(from: safeData) {
                        self.delegate?.didUpdateData(with: self,with: parsedData)
                    }
                }
            }
        }
        task.resume()
    }

  func makeHttpBody(from StringData: String) -> [String: Any] {
        switch StringData {
        case K.balanceUrl:
            return K.authorization
        case K.projectsUrl:
            return K.projects
        default:
            return ["none" : "none"]
        }
    }

解决方法

您的方法行不通,您必须使用限制为 Decodable 的泛型类型。在运行时检查字符串不是一个好习惯。

这是您代码的简化版本,错误已移交给调用方

func parseJSON<T : Decodable>(from data: Data) throws -> T {
    return try JSONDecoder().decode(T.self,from: data)
}

然后就可以写了(返回类型一定要注解)

let result : [Foo] = try parseJSON(from: data)

或者如果你想在函数中指定类型

func parseJSON<T : Decodable>(from data: Data,type : T.Type) throws -> T {
    return try JSONDecoder().decode(T.self,from: data)
}

let result = try parseJSON(from: data,type: [Foo].self)