Swift 5 + Alamofire 5.*: 解码顶部具有相同根对象的数据
Swift 5 + Alamofire 5.*: Decode data with same root object at the top
我的问题是我有 JSON 从服务器获取的对象,如下所示:
{
"data": [
{
"id": 1,
"name": "at",
"amount": 446,
"createdAt": "25/04/2020",
"updatedAt": "25/04/2020"
},
{
"id": 2,
"name": "iste",
"amount": 872,
"createdAt": "25/04/2020",
"updatedAt": "25/04/2020"
}
]
}
而且我有解码这个对象的 Codable 结构:
struct Expense: Codable, Identifiable {
var id: Int
var name: String
var amount: String
var createdAt: String
var updatedAt: String
}
另外,我 class 有一个静态方法来执行 AF 请求,我还使用 FuturePromise 库来处理请求的完成:
struct RequestAPI {
@discardableResult
static func callAndDecode<T:Decodable>(route:APIRouter, decoder: JSONDecoder = JSONDecoder()) -> Future<T> {
return Future(operation: { completion in
AF.request(route).responseDecodable(decoder: decoder, completionHandler: { (response: DataResponse<T, AFError>) in
switch response.result {
case .success(let value):
completion(.success(value))
case .failure(let error):
print(error.localizedDescription)
completion(.failure(error))
}
})
})
}
}
问题是我有一个根 "data" 参数有时存在有时不存在。
我知道有一个解决方案,我可以创建一个结果编码模型,该模型将成为费用模型的父级,但这并没有达到我想要的效果,因为如果我有 20 个不同的模型会发生什么我必须创建 20 个不同的根模型吗?
是的,我可以使用 CodingKeys 来完成,但是对于这个简单的任务来说这有点老套而且代码太多了。
所以最好的方法是添加如下内容:
struct ExpensesList: Codable {
var data: [Expense]
}
但对我来说,问题是我将始终拥有 'data' root,因此对于任何模型,我都会有一些 'List' 模型。
是否有更好的方法而不是 hacky 或者这是唯一的方法。
也许可以将子模型发送到一个数据模型,但是如何在视图中识别它,...?
提前致谢。
如果我理解正确,你可以使你的 Root
结构通用,并且还应该使 data
属性 可选。
struct Foo: Decodable {
let foo: Int
}
struct Bar: Decodable {
let bar: String
}
struct Root<T: Decodable>: Decodable {
let data: [T]?
}
typealias FooList = Root<Foo>
typealias BarList = Root<Bar>
let fooData = """
{ "data": [ { "foo": 42 } ] }
""".data(using: .utf8)!
let barData = """
{ "data": [ { "bar": "baz" } ] }
""".data(using: .utf8)!
do {
let foos = try JSONDecoder().decode(FooList.self, from: fooData)
let bars = try JSONDecoder().decode(BarList.self, from: barData)
} catch {
print(error)
}
我的问题是我有 JSON 从服务器获取的对象,如下所示:
{
"data": [
{
"id": 1,
"name": "at",
"amount": 446,
"createdAt": "25/04/2020",
"updatedAt": "25/04/2020"
},
{
"id": 2,
"name": "iste",
"amount": 872,
"createdAt": "25/04/2020",
"updatedAt": "25/04/2020"
}
]
}
而且我有解码这个对象的 Codable 结构:
struct Expense: Codable, Identifiable {
var id: Int
var name: String
var amount: String
var createdAt: String
var updatedAt: String
}
另外,我 class 有一个静态方法来执行 AF 请求,我还使用 FuturePromise 库来处理请求的完成:
struct RequestAPI {
@discardableResult
static func callAndDecode<T:Decodable>(route:APIRouter, decoder: JSONDecoder = JSONDecoder()) -> Future<T> {
return Future(operation: { completion in
AF.request(route).responseDecodable(decoder: decoder, completionHandler: { (response: DataResponse<T, AFError>) in
switch response.result {
case .success(let value):
completion(.success(value))
case .failure(let error):
print(error.localizedDescription)
completion(.failure(error))
}
})
})
}
}
问题是我有一个根 "data" 参数有时存在有时不存在。
我知道有一个解决方案,我可以创建一个结果编码模型,该模型将成为费用模型的父级,但这并没有达到我想要的效果,因为如果我有 20 个不同的模型会发生什么我必须创建 20 个不同的根模型吗?
是的,我可以使用 CodingKeys 来完成,但是对于这个简单的任务来说这有点老套而且代码太多了。
所以最好的方法是添加如下内容:
struct ExpensesList: Codable {
var data: [Expense]
}
但对我来说,问题是我将始终拥有 'data' root,因此对于任何模型,我都会有一些 'List' 模型。
是否有更好的方法而不是 hacky 或者这是唯一的方法。
也许可以将子模型发送到一个数据模型,但是如何在视图中识别它,...?
提前致谢。
如果我理解正确,你可以使你的 Root
结构通用,并且还应该使 data
属性 可选。
struct Foo: Decodable {
let foo: Int
}
struct Bar: Decodable {
let bar: String
}
struct Root<T: Decodable>: Decodable {
let data: [T]?
}
typealias FooList = Root<Foo>
typealias BarList = Root<Bar>
let fooData = """
{ "data": [ { "foo": 42 } ] }
""".data(using: .utf8)!
let barData = """
{ "data": [ { "bar": "baz" } ] }
""".data(using: .utf8)!
do {
let foos = try JSONDecoder().decode(FooList.self, from: fooData)
let bars = try JSONDecoder().decode(BarList.self, from: barData)
} catch {
print(error)
}