Ошибка несоответствия типа декодера JSON

Я хочу разобрать JSON с помощью декодируемого, но получаю несоответствие типа ошибки, например:

Swift.DecodingError.Context(codingPath: [], debugDescription: «Ожидается декодирование массива, но вместо этого найден словарь».

Мой JSON:

{
  "code": 0,
  "data": {
    "_id": "string",
    "title": "string",
    "images": [
      "string"
    ],
    "shortDesc": "string",
    "desc": "string",
    "price": 0,
    "discountPrice": 0,
    "quantity": 0,
    "category": {
      "name": "string",
      "val": "string"
    },
    "brand": {
      "name": "string",
      "val": "string"
    },
    "variants": [
      {
        "name": "string",
        "value": "string",
        "quantity": 0,
        "variantCode": "string"
      }
    ],
    "stockCode": "string",
    "updatedDate": "2018-06-05T14:04:51.226Z",
    "status": true,
    "isDeleted": true,
    "isNew": true,
    "freeCargo": true,
    "createDate": "2018-06-05T14:04:51.226Z",
    "note1": "string",
    "note2": "string",
    "note3": "string",
    "shop": {
      "name": "string",
      "val": "string"
    }
  },
  "error": "string"
}

МОЯ МОДЕЛЬ:

struct ProductDetail : Decodable {
        let code : Int = 0
        let error : String = ""
        var data : NestedData? = nil
}

ВЛОЖЕННЫЕ ДАННЫЕ:

struct NestedData : Decodable{
    let _id : String = ""
    let title : String = ""
    let images : [String] = []
    let shortDesc : String = ""
    let desc : String = ""
    let price : Int = 0
    let discountPrice : Int = 0
    let quantity : Int = 0
    let updatedDate : String = ""
    let status : Bool = false
    let isDeleted : Bool = false
    let isNew : Bool = false
    let freeCargo : Bool = false
    let createDate : String = ""
    let note1: String = ""
    let note2: String = ""
    let note3: String = ""
    let variants : [variants]? = nil
    let brand : brand? = nil
    let category :category? = nil
    let shop : shop? = nil

}

ОБЪЕКТЫ:

struct variants : Decodable{
    let name : String
    let val : String
    let quantity : Int
    let variantCode : String
}

struct brand : Decodable{
    let name : String
    let val : String
}

struct category : Decodable{
    let name : String
    let val : String
}

struct shop : Decodable{
    let name : String
    let val : String
}

Я не понимаю, почему я получаю сообщение об ошибке, Консоль говорит, что ожидается массив, но словарь найден, но, к сожалению, я не понимаю.


person Akif Demirezen    schedule 05.06.2018    source источник
comment
Я только что проверил ваши декодируемые структуры, и они, похоже, работают. Возможно, вы пытаетесь декодировать массив ProductDetails — либо в строке JSON, полученной с сервера, либо по предоставленному типу в JSONDecoder.   -  person Dan Karbayev    schedule 05.06.2018
comment
В качестве примечания: если вы предоставляете значения по умолчанию для своей кодируемой структуры и используете автоматически сгенерированный декодер, значения не будут декодированы из JSON, и вместо них будут использоваться значения по умолчанию.   -  person Dan Karbayev    schedule 05.06.2018
comment
может быть, вы говорите правильно, но как точно изменить значения по умолчанию?   -  person Akif Demirezen    schedule 05.06.2018


Ответы (3)


Хорошо, я советую вам использовать quicktype

это поможет вам сделать вашу модель

Я использую его, и это Модель

struct ProductDetail: Codable {
    let code: Int?
    let data: DataClass?
    let error: String?
}

struct DataClass: Codable {
    let id, title: String?
    let images: [String]?
    let shortDesc, desc: String?
    let price, discountPrice, quantity: Int?
    let category, brand: Brand?
    let variants: [Variant]?
    let stockCode, updatedDate: String?
    let status, isDeleted, isNew, freeCargo: Bool?
    let createDate, note1, note2, note3: String?
    let shop: Brand?

    enum CodingKeys: String, CodingKey {
        case id = "_id"
        case title, images, shortDesc, desc, price, discountPrice, quantity, category, brand, variants, stockCode, updatedDate, status, isDeleted, isNew, freeCargo, createDate, note1, note2, note3, shop
    }
}

struct Brand: Codable {
    let name, val: String?
}

struct Variant: Codable {
    let name, value: String?
    let quantity: Int?
    let variantCode: String?
}

после этого вы можете использовать JSONDecoder

Alamofire.request(urlCourses, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil).responseJSON { (response) in

        switch response.result {

        case .success:

            guard let data = response.data else { return }

            do {

                let productDetail = try? JSONDecoder().decode(ProductDetail.self, from: jsonData)

            } catch let jsonError {

                print("Error serializing json:", jsonError)
            }

        case .failure(let error):

            print(error)
        }
}
person Abdelrahman Mohamed    schedule 11.06.2018
comment
WOOOW спасибо за ссылку на инструмент быстрого ввода!!! никогда не слышал об этом до сих пор!! игра чейнджер!! сэкономишь мне столько времени!! отличная акция @Abdelrahman - person ll_cool_aid; 30.07.2020

Я думаю, что в вашем коде нет ошибок, возможно, это ваша ошибка в First response
, поэтому дважды проверьте это.

Вот ваша модель:

  import Foundation

    struct ProductDetail: Codable {
        let code: Int
        let data: NestedData?
        let error: String?
    }

    struct NestedData: Codable {
        let id, title: String
        let images: [String]
        let shortDesc, desc: String
        let price, discountPrice, quantity: Int
        let category:Category
        let brand: Brand
        let variants: [Variant]
        let stockCode, updatedDate: String
        let status, isDeleted, isNew, freeCargo: Bool
        let createDate, note1, note2, note3: String
        let shop: Shop

        enum CodingKeys: String, CodingKey {
            case id = "_id"
            case title, images, shortDesc, desc, price, discountPrice, quantity, category, brand, variants, stockCode, updatedDate, status, isDeleted, isNew, freeCargo, createDate, note1, note2, note3, shop
        }
    }

    struct Brand: Codable {
        let name, val: String
    }
    struct Category: Codable {
        let name, val: String
    }

    struct Shop : Codable{
        let name : String
        let val : String
    }



    struct Variant: Codable {
        let name, value: String
        let quantity: Int
        let variantCode: String
    }


    extension ProductDetail {
        init(data: Data) throws {
            self = try JSONDecoder().decode(ProductDetail.self, from: data)
        }
    }

Здесь, как использовать:

switch response.result {
case .success:
    guard let data = response.data else { return }
    let productDetail = try? ProductDetail.init(data: data){

        //
    }
}
person Abdelahad Darwish    schedule 05.06.2018
comment
Спасибо за ответ, но он не сработал, я думаю, что-то не так с другой стороны - person Akif Demirezen; 05.06.2018

Либо ответ вашего сервера немного отличается от указанного выше, либо у вас есть:

let result = try JSONDecoder().decode([ProductDetail].self, from: jsonData)

вместо правильного:

let result = try JSONDecoder().decode(ProductDetail.self, from: jsonData)

Я протестировал приведенный выше JSON на игровой площадке и попытался декодировать, используя структуры, которые вы разместили в своем коде, и это сработало. Если бы я добавил [] вокруг ProductDetail, я бы получил ошибку.

person Scriptable    schedule 05.06.2018
comment
Я пробовал это раньше, но не получил результата, я думаю, что структура в порядке, но я не понимаю своей ошибки - person Akif Demirezen; 05.06.2018
comment
Вы показываете JSON и структуры, которые работают. что-то не сходится. покажите код где вы декодируете. если вы хотите получить хороший ответ, вам нужно предоставить всю информацию. - person Scriptable; 05.06.2018
comment
У меня есть переменная var productObserver = Box‹ProductDetail›(), и здесь я получаю сообщение об ошибке, я думаю, switch response.result { case .success: guard let data = response.data else { return } do { self.decoder.keyDecodingStrategy = .useDefaultKeys let product = try self.decoder.decode(ProductDetail.self, from: data) self.productObserver.value? = продукт - person Akif Demirezen; 05.06.2018