декодер json не может быстро декодировать данные json

в моем коде я не могу расшифровать свой ответ, который я получаю от API. Я нахожу данные, но мой декодер не может их расшифровать, я пытался найти проблему, но не могу это выяснить.

Мой код:

var request = URLRequest(url: URL(string: "http://wsapi.easyservice.xyz/api/v1/carts/2")!,timeoutInterval: Double.infinity)
        request.addValue("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImI0YzFkOTRhN2ZmN2I0OGE1MTI3ZWMyZTAxYzJhYzMxNzRkODIxYjVkYTlhMTE3N2NlNTUxODViNTZjZDEyNjY2NWI2ZjVhOGU2NTM1ZDExIn0.eyJhdWQiOiIxIiwianRpIjoiYjRjMWQ5NGE3ZmY3YjQ4YTUxMjdlYzJlMDFjMmFjMzE3NGQ4MjFiNWRhOWExMTc3Y2U1NTE4NWI1NmNkMTI2NjY1YjZmNWE4ZTY1MzVkMTEiLCJpYXQiOjE2MDU1MDk1MDEsIm5iZiI6MTYwNTUwOTUwMSwiZXhwIjoxNjM3MDQ1NTAxLCJzdWIiOiI0NTIiLCJzY29wZXMiOltdfQ.cHR-jRG4atU8DtwqiQtxV9vjRg4CMR9dYH8AGpgKgOmbylSLlf8eYf76LmwVOZl9Ii1uxHXvK95_43suYuO_6REE_pMEgRKELxM9LZVPSt6VboXENqwBZ_1GCu4nobBUPPqC56SXYqTVaLlTSjts7O3kpXrPqhrEIWV0UQYq9KS6bUFMkQuuyDrXoL6JVuJ-ntUzU42QgXjaQ0usQah3-gJZGAB684bp6LP3_RTInuIDKarGERPKHIFz94V_jvpkixKBUQW1uDJpcSh9v2ZR1PVlQ1pMaYGaZN50OrTkqY9NTi16PpUhOrmzCcXFLxWC4S-s2FDlXfPZNS-1kEIguS38ecydyBW_FHSzJQFQHZ5STTNiLxB8B5-6OUwEaaXBl9XuJJBlcmUrMiQNjqb2TXL9ZNw1R6Htqgrn2En0RjgzuWXSLui1PgkyRJMifg2cphPpQlNhgkXqZrPz27_xp8CCfUjdiEFEWFdFj-4_grRPjLXA48alG6KeFGi_Vu65rVNCz9yF5M4U43G9KJZCg8-nppKZ623OvE4YxU8IS7SuTuQIHChFPaVef-D7GYLnZEPl7L7bo5IuUiwZ67wP0zieKsEya3_LDNy_tUG48k-y5KTl0OOIn4GtmDdCAK4qKcAC_0OjWmktesJRbgh3Nm9O_CIl_DBUZ89fMks0SsA", forHTTPHeaderField: "Authorization")

        request.httpMethod = "GET"

        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            
            if let jsonResponse = try? JSONDecoder().decode(GetItCartModel.self, from: data!) {
                print(jsonResponse)
            }
          guard let data = data else {
            print(String(describing: error))
            
            return
          }
          print(String(data: data, encoding: .utf8)!)
          
        }

        task.resume()

и я использую эту модель как GetItCartModel

// MARK: - GetItCartModel
struct GetItCartModel: Codable {
    var success: Bool?
    var message: String?
    var data: GetItCartModelDataClass?
}

// MARK: - DataClass
struct GetItCartModelDataClass: Codable {
    var id, userID, serviceID: Int?
    var createdAt, updatedAt: String?
    var items: [GetItCartModelItem]?

    enum CodingKeys: String, CodingKey {
        case id
        case userID = "user_id"
        case serviceID = "service_id"
        case createdAt = "created_at"
        case updatedAt = "updated_at"
        case items
    }
}

// MARK: - Item
struct GetItCartModelItem: Codable {
    var id, cartID: Int?
    var details: GetItCartModelDetails?
    var attachments: JSONNull?
    var quantity, createdAt, updatedAt: String?

    enum CodingKeys: String, CodingKey {
        case id
        case cartID = "cart_id"
        case details, attachments, quantity
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }
}

// MARK: - Details
struct GetItCartModelDetails: Codable {
    var brandID: Int?
    var brandName: String?
    var icategoryIdd: Int?
    var categoryName, endDate: String?
    var id, orderItemPrice: Int?
    var product: Product?
    var quantity: Int?
    var startDate: String?
    var totalDays: Int?
    var typeID: Int?
    var typeName: String?

    enum CodingKeys: String, CodingKey {
        case brandID = "brandId"
        case brandName, icategoryIdd, categoryName, endDate, id, orderItemPrice, product, quantity, startDate, totalDays
        case typeID = "typeId"
        case typeName
    }
}



// MARK: - Product
struct GetItCartModelProduct: Codable {
    var categorizableID: Int?
    var createdAt, productDescription: String?
    var id: Int?
    var price: String?
    var thumbnail: String?
    var title, updatedAt: String?

    enum CodingKeys: String, CodingKey {
        case categorizableID = "categorizable_id"
        case createdAt = "created_at"
        case productDescription = "description"
        case id, price, thumbnail, title
        case updatedAt = "updated_at"
    }
}

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

Примечание. Вот ответ почтальона в формате JSON.

{
    "success": true,
    "message": "items list",
    "data": {
        "id": 23,
        "user_id": 452,
        "service_id": 2,
        "created_at": "2020-11-16 13:21:36",
        "updated_at": "2020-11-16 13:21:36",
        "items": [
            {
                "id": 54,
                "cart_id": 23,
                "details": {
                    "brandId": 44,
                    "brandName": "Apple",
                    "icategoryIdd": 41,
                    "categoryName": "Mobile Equipment",
                    "endDate": "2020-12-26",
                    "id": 0,
                    "orderItemPrice": 4920,
                    "product": {
                        "categorizable_id": 44,
                        "created_at": "2020-07-24 05:46:07",
                        "description": "Description",
                        "id": 11,
                        "price": "120.00",
                        "thumbnail": "https://hexamatics.s3.ap-south-1.amazonaws.com/app/photos/product/kkoBnHm7cqjWzPTh4nPdaxuPaTDylNdNDqlCFKLz.jpeg",
                        "title": "Test product",
                        "updated_at": "2020-08-25 12:14:21"
                    },
                    "quantity": 1,
                    "startDate": "2020-11-16",
                    "totalDays": 41,
                    "typeId": 42,
                    "typeName": "Display"
                },
                "attachments": null,
                "quantity": "1",
                "created_at": "2020-11-16 13:21:36",
                "updated_at": "2020-11-16 13:21:36"
            },
            {
                "id": 97,
                "cart_id": 23,
                "details": {
                    "categoryName": "Mobile Equipment",
                    "startDate": "2020-11-18 09:20:32 +0000",
                    "brandId": "44",
                    "product": {
                        "thumbnail": "https://hexamatics.s3.ap-south-1.amazonaws.com/app/photos/product/kkoBnHm7cqjWzPTh4nPdaxuPaTDylNdNDqlCFKLz.jpeg",
                        "categorizable_id": 44,
                        "created_at": "2020-07-24 05:46:07",
                        "title": "Test product",
                        "updated_at": "2020-08-25 12:14:21",
                        "description": "Description",
                        "id": 11,
                        "price": "120.00"
                    },
                    "icategoryIdd": "41",
                    "typeId": "42",
                    "typeName": "Display",
                    "brandName": "Apple",
                    "quantity": "1",
                    "endDate": "2020-11-18 09:20:36 +0000"
                },
                "attachments": null,
                "quantity": "1",
                "created_at": "2020-11-18 09:20:51",
                "updated_at": "2020-11-18 09:20:51"
            },
            {
                "id": 98,
                "cart_id": 23,
                "details": {
                    "brandId": 44,
                    "brandName": "Apple",
                    "icategoryIdd": 41,
                    "categoryName": "Mobile Equipment",
                    "endDate": "2020-11-18",
                    "id": 0,
                    "orderItemPrice": 120,
                    "product": {
                        "categorizable_id": 44,
                        "created_at": "2020-07-24 05:46:07",
                        "description": "Description",
                        "id": 11,
                        "price": "120.00",
                        "thumbnail": "https://hexamatics.s3.ap-south-1.amazonaws.com/app/photos/product/kkoBnHm7cqjWzPTh4nPdaxuPaTDylNdNDqlCFKLz.jpeg",
                        "title": "Test product",
                        "updated_at": "2020-08-25 12:14:21"
                    },
                    "quantity": 1,
                    "startDate": "2020-11-18",
                    "totalDays": 1,
                    "typeId": 42,
                    "typeName": "Display"
                },
                "attachments": null,
                "quantity": "1",
                "created_at": "2020-11-18 10:16:18",
                "updated_at": "2020-11-18 10:16:18"
            }
        ]
    }
}

person Al Mustakim    schedule 18.11.2020    source источник
comment
Как мы можем это сделать, если мы не знаем, что такое ответ (json)? Однако в качестве первого шага вы никогда не должны делать try? при декодировании json, загруженного из какого-либо API. Используйте try с do/catch и напечатайте ошибку в улове, catch { print(error) }. Может быть, это даже поможет вам решить эту проблему самостоятельно :). Еще одна вещь, которую я только что заметил, это то, что вы сначала пытаетесь декодировать данные, а затем проверяете, получили ли вы какие-либо данные, это, конечно, должно быть сделано в обратном порядке.   -  person Joakim Danielson    schedule 18.11.2020
comment
Спасибо, я отредактировал вопрос с данными json, но здесь я получаю ошибку typeMismatch, когда печатаю ошибку. но я не могу сделать свои сущности похожими на ответ. Я получаю int , но когда я определяю int , это не декодирование с несоответствием типа ошибки   -  person Al Mustakim    schedule 18.11.2020


Ответы (2)


У меня есть решение, я использовал тип JSONAny, где отображается ошибка typeMismatch. как я сделал модель:

struct ITBase : Codable {
    let success : Bool?
    let message : String?
    let data : ITData?
    
}


struct ITData : Codable {
    let id : JSONAny?
    let user_id : JSONAny?
    let service_id : JSONAny?
    let created_at : String?
    let updated_at : String?
    let items : [ITItems]?
    
    
}


struct ITDetails : Codable {
    let brandId : JSONAny?
    let brandName : String?
    let icategoryIdd : JSONAny?
    let categoryName : String?
    let endDate : String?
    let id : JSONAny?
    let orderItemPrice : JSONAny?
    let product : ITProduct?
    let quantity : JSONAny?
    let startDate : String?
    let totalDays : JSONAny?
    let typeId : JSONAny?
    let typeName : String?
    
}


struct ITItems : Codable {
    let id : JSONAny?
    let cart_id : JSONAny?
    let details : ITDetails?
    let attachments : JSONAny?
    let quantity : JSONAny?
    let created_at : String?
    let updated_at : String?
    
}

struct ITProduct : Codable {
    let categorizable_id : JSONAny?
    let created_at : String?
    let description : String?
    let id : JSONAny?
    let price : JSONAny?
    let thumbnail : String?
    let title : String?
    let updated_at : String?
    
    
}

но я не знаю, это решение хорошо или плохо. если у вас есть лучшее решение, вы можете предложить мне.

person Al Mustakim    schedule 18.11.2020
comment
Что это, SwiftyJSON или? Я бы не рекомендовал решение, как это, потому что вы будете только продвигать проблему вперед, и вам нужно будет добавлять дополнительную логику всякий раз, когда вы хотите получить доступ к любому из свойств типа JSONAny. - person Joakim Danielson; 18.11.2020
comment
Теперь у меня есть это, спасибо за вашу помощь @JoakimDanielson - person Al Mustakim; 18.11.2020
comment
неверные параметры. brandId, typeID могут иметь разные типы: String или Int по запросу. - person Kiryl Belasheuski; 18.11.2020

Похоже, что json, который вы получаете, не очень согласован, и некоторые целые значения задаются как в виде строк, так и в виде целых чисел.

Поэтому вам нужно добавить пользовательский init(from:) к типу GetItCartModelDetails и обрабатывать там оба сценария. Я начал писать один, как показано ниже, но вы, конечно, должны добавить все свойства GetItCartModelDetails в этот метод инициализации.

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    if let temp = try? container.decode(Int.self, forKey: .brandID) {
        brandID = temp
    } else {
        brandID = Int(try container.decode(String.self, forKey: .brandID)) ?? 0
    }
    brandName = try container.decode(String.self, forKey: .brandName)
    if let temp = try? container.decode(Int.self, forKey: .icategoryIdd) {
        icategoryIdd = temp
    } else {
        icategoryIdd = Int(try container.decode(String.self, forKey: .icategoryIdd)) ?? 0
    }
    categoryName = try container.decode(String.self, forKey: .categoryName)
    if let temp = try? container.decode(Int.self, forKey: .quantity) {
        quantity = temp
    } else {
        quantity = Int(try container.decode(String.self, forKey: .quantity)) ?? 0
    }
    //add all other properties here.
}

Вы установили почти все свои свойства как необязательные, что неверно, только пусть те свойства, которые вы знаете, могут быть нулевыми, могут быть объявлены необязательными.

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

person Joakim Danielson    schedule 18.11.2020