Декодирование данных с использованием Codable - PullRequest
0 голосов
/ 08 февраля 2019

Я пытаюсь декодировать массив объектов моей модели (Каталог) из JSON, который выглядит следующим образом после сериализации соответствующего объекта «Данные».

 { "id" : 5,
   "catalogs" : [ {catalogKeyValue1},{catalogKeyValue2}]
 }

Мой объект модели выглядит следующим образом

struct Catalog : Codable{
 var id : Int
 var name : String
 var categoryId : Int
 var minProductPrice : Int
 var maxProductDiscount : Int?
 var shareText : String
 var collageImage : String
 var collageImageAspectRatio : Double?
 var shipping : [String : Int]?
 var description : String
}

Мне нужно получить массив каталогов (который вложен в ключ 'catalogs' в JSON) после декодирования. Я полностью понимаюиспользование вложенных контейнеров и написание собственного инициализатора для структуры Каталога. Как я могу достичь этого без необходимости писать другую структуру Codable для внешнего JSOn, которая выглядит следующим образом

struct CatalogArray: Codable {
 var catalogs : [Catalog]
}

, а затем сделать что-то подобное, чтобы получить декодированный массивкаталогов

let catalogArray = try decoder.decode(CatalogArray.self, from: validData)

Моя проблема в том, что мне не нужна эта структура catalogArray.Существует ли способ декодирования объектов модели Каталога без создания ненужных вложенных структур.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Согласно вашему комментарию

Проблема с большим количеством Codable структур заключается в том, что мне потребуется создать другую структуру, если тот же массив каталогов содержит другой ключ в другом ответе API.

Вы можете создать общую структуру, которая может сделать то же самое для вас.Вот пример

struct GeneralResponse<T:Codable>: Codable {
    let code: Int
    let catalogs: T?

    enum CodingKeys: String, CodingKey {
        case code = "id"
        case catalogs = "catalogs"
    }

    public init(from decoder:Decoder) throws {
        let contaienr = try  decoder.container(keyedBy: CodingKeys.self)
        code = try contaienr.decode(Int.self, forKey: .code)


        do {
            let object = try contaienr.decodeIfPresent(T.self, forKey: .data)
            catalogs = object

        } catch {
            catalogs = nil
        }

    }

}

Сейчас

Вы можете использовать это с различными каталогами типа структуры

как

GeneralResponse<[Catalogs]> или GeneralResponse<[CatalogsAnother]>

Надеюсь, это полезно

0 голосов
/ 08 февраля 2019

Вы можете сделать это вместо создания новой структуры каждый раз: try container.decode([Catalog].self, forKey: "Catalogs")

Массивы типа Codable автоматически кодируются.

...