在单个函数中解析远程 JSON 而不在 Swift 中创建模型
Parse remote JSON without creating models in Swift, in a single function
我的应用程序必须通过 HTTPS 请求获取 JSON,然后解析该数据。
我正在寻找的是采用“一个功能统治所有”的方法,就像这样。
func call(endpoint: String) {
let url = URL(string: "https://example.com/api/"+endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// Parse JSON here without using a model.
// Just convert the data into a JSON object and return it
}
}
在我看来,我遇到的每个示例代码都需要创建一个具有预期值的模型,然后执行此操作:
JSONDecoder().decode(ModelHere.self, from: data)
这意味着我需要为每个端点创建一个新函数。
为什么不为每个端点使用单独的函数?
我有很多端点可以从一个函数中调用。
为每个端点创建一个新函数,将一个单独的模型传递给它,然后从响应中解析数据……代码中有很多垃圾需要筛选。
我敢肯定有更好的方法来做到这一点只是晦涩难懂,或者我错过了。
基本上,我正在寻找这个:
函数需要远程数据来加载视图 -> 触发调用('endpoint/example/') -> call() returns json 对象 -> 函数现在可以获取它需要的数据
多个处理器函数,一个 call() 函数。我希望我说得有道理。
谢谢
这就是 generic
的用途,例如:
您可以将 T
定义为通用类型的日期模型,然后获取它并 return 它完成。使 T
成为可编码的,因此任何符合 codable
的模型都会进行此调用。
func call<T: Codable>(endpoint: String, completion: (T) -> ()) {
let url = URL(string: "https://example.com/api/"+endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// Parse JSON here without using a model.
// Just convert the data into a JSON object and return it
let model = JSONDecoder().decode(T.self, from: data)
completion(model)
}
}
当你调用函数时:
call(endpoint: "something") { model: ModelHere in
// Use your model
}
因此您不必为您拥有的每个模型制作单独的函数。
** 代码未经测试,仅供参考
编辑:这是一个带有评论反馈的示例(谢谢@Leo)
private var host = "https://jsonplaceholder.typicode.com/"
enum NetworkError: Error {
case invalidUrl
case invalidData
case underlying(_ error: Error)
}
func call<T: Decodable>(endpoint: String,
completion: @escaping (Result<T, NetworkError>) -> ()) -> Bool
{
guard let url = URL(string: host+endpoint) else {
completion(.failure(.invalidUrl))
return false
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
return completion(.failure(.invalidData))
}
do {
let model = try JSONDecoder().decode(T.self, from: data)
completion(.success(model))
} catch let error {
print(error.localizedDescription)
completion(.failure(.underlying(error)))
}
}.resume()
return true
}
当您调用函数时:
struct SampleModel: Decodable {
let id: Int
let content: String
}
func sample() {
let isSuccess = call(endpoint: "fetchSampleModelUrl") { (result: Result<[SampleModel], NetworkError>) in
switch result {
case .success(let model):
print("\(model)")
case .failure(let error):
print("\(error)")
}
}
}
我的应用程序必须通过 HTTPS 请求获取 JSON,然后解析该数据。
我正在寻找的是采用“一个功能统治所有”的方法,就像这样。
func call(endpoint: String) {
let url = URL(string: "https://example.com/api/"+endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// Parse JSON here without using a model.
// Just convert the data into a JSON object and return it
}
}
在我看来,我遇到的每个示例代码都需要创建一个具有预期值的模型,然后执行此操作:
JSONDecoder().decode(ModelHere.self, from: data)
这意味着我需要为每个端点创建一个新函数。
为什么不为每个端点使用单独的函数?
我有很多端点可以从一个函数中调用。
为每个端点创建一个新函数,将一个单独的模型传递给它,然后从响应中解析数据……代码中有很多垃圾需要筛选。
我敢肯定有更好的方法来做到这一点只是晦涩难懂,或者我错过了。
基本上,我正在寻找这个:
函数需要远程数据来加载视图 -> 触发调用('endpoint/example/') -> call() returns json 对象 -> 函数现在可以获取它需要的数据
多个处理器函数,一个 call() 函数。我希望我说得有道理。
谢谢
这就是 generic
的用途,例如:
您可以将 T
定义为通用类型的日期模型,然后获取它并 return 它完成。使 T
成为可编码的,因此任何符合 codable
的模型都会进行此调用。
func call<T: Codable>(endpoint: String, completion: (T) -> ()) {
let url = URL(string: "https://example.com/api/"+endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// Parse JSON here without using a model.
// Just convert the data into a JSON object and return it
let model = JSONDecoder().decode(T.self, from: data)
completion(model)
}
}
当你调用函数时:
call(endpoint: "something") { model: ModelHere in
// Use your model
}
因此您不必为您拥有的每个模型制作单独的函数。
** 代码未经测试,仅供参考
编辑:这是一个带有评论反馈的示例(谢谢@Leo)
private var host = "https://jsonplaceholder.typicode.com/"
enum NetworkError: Error {
case invalidUrl
case invalidData
case underlying(_ error: Error)
}
func call<T: Decodable>(endpoint: String,
completion: @escaping (Result<T, NetworkError>) -> ()) -> Bool
{
guard let url = URL(string: host+endpoint) else {
completion(.failure(.invalidUrl))
return false
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
return completion(.failure(.invalidData))
}
do {
let model = try JSONDecoder().decode(T.self, from: data)
completion(.success(model))
} catch let error {
print(error.localizedDescription)
completion(.failure(.underlying(error)))
}
}.resume()
return true
}
当您调用函数时:
struct SampleModel: Decodable {
let id: Int
let content: String
}
func sample() {
let isSuccess = call(endpoint: "fetchSampleModelUrl") { (result: Result<[SampleModel], NetworkError>) in
switch result {
case .success(let model):
print("\(model)")
case .failure(let error):
print("\(error)")
}
}
}