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 type, където показва грешка 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 метод

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