Swift 5 + Alamofire 5.*:解码顶部具有相同根对象的数据

Posted

技术标签:

【中文标题】Swift 5 + Alamofire 5.*:解码顶部具有相同根对象的数据【英文标题】:Swift 5 + Alamofire 5.*: Decode data with same root object at the top 【发布时间】:2020-04-26 12:49:34 【问题描述】:

我的问题是我有像这样从服务器获取的 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

另外,我有一个带有静态方法的类,它将执行 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))
                
          )
      )
    

问题是我有一个有时存在有时不存在的根“数据”参数。

我知道有一个解决方案可以创建一个可编码的结果模型,该模型将成为费用模型的父级,但这并没有达到我想要的效果,因为如果我有 20 个不同的模型会发生什么?必须创建 20 个不同的根模型吗?

是的,我可以使用 CodingKeys 来完成,但对于这个简单的任务来说,这有点笨拙而且代码太多。

所以最好的方法是添加如下内容:

struct ExpensesList: Codable 
    var data: [Expense]

但对我来说,我总是有“数据”根是一个问题,所以对于任何模型我都会有一些“列表”模型。

有没有更好的方法而不是hacky或者这是唯一的方法。

也许将子模型发送到一个数据模型,但是如何在视图中识别它,...?

提前谢谢你。

【问题讨论】:

【参考方案1】:

如果我理解正确,您可以将 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)

【讨论】:

是的,这是一种方法,这就是为什么我说:“也许将子模型发送到一个数据模型,但是如何在视图中识别它,...?”但是我尝试了这个,它工作得很好,但是我对如何在视图中呈现这些数据有一些误解,它工作得很好。非常感谢。

以上是关于Swift 5 + Alamofire 5.*:解码顶部具有相同根对象的数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Alamofire 5.0.0-beta.3 (Swift 5) 上传图片(多部分)

如何使用 Swift 5 在 Xcode 10.2.1 中添加 alamofire

使用 swift 5 请求 AlamoFire url

Alamofire Swift 5:传递参数时抛出错误

使用 PHP 在 Swift 5 中使用 Alamofire 接收图像上传

Swift AlamoFire 5 不会执行请求