Swift 5 + Alamofire 5. *: декодировать данные с тем же root объектом вверху - PullRequest
0 голосов
/ 26 апреля 2020

Моя проблема в том, что у меня есть 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
}

Также , У меня есть класс с методом stati c, который будет выполнять запрос 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))
                }
          })
      })
    }
}

Проблема в том, что у меня root " Параметр data », который иногда присутствует, а иногда нет.

Я знаю, что есть решение, в котором я могу создать кодируемую модель результатов, которая будет родительской для модели затрат, но которая не подходит мне потому что, что произойдет, если у меня будет 20 разных моделей, мне нужно будет создать 20 различных root моделей?

Да, я могу сделать это с помощью CodingKeys, но это немного глупо и слишком много код для этой простой задачи.

Так что лучший подход - добавить что-то вроде этого:

struct ExpensesList: Codable {
    var data: [Expense]
}

Но для меня это проблема, что у меня всегда будут «данные» root, то для любого мода У меня будет какая-то модель 'List'.

Есть ли лучший подход, который не является хакерским или это единственный.

Может быть, отправить дочернюю модель в одну модель данных, но как распознать его по взглядам, ...?

Заранее спасибо.

1 Ответ

0 голосов
/ 26 апреля 2020

Если я вас правильно понимаю, вы можете сделать структуру Root обобщенной c, а также сделать свойство 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)
}
...