1

Different api responses, not getting handled in code. Need to parse the array but my code expecting dictionary, I am not getting where to change. Please guide. Below is code:

func fetchProducts() {
    print("Page no\(String(describing: filter.page) )")

    NetworkHelper().makeAPIRequest(forAPI: .getProducts(forProduct: filter), responseType: ProductsDescription.self) { [weak self] (result) in

        guard let `self` = self else { return }
        switch result{
        case .error(let error):
            self.delegate?.ProductListing(self, didGetError: error)
        case .success(let response,let responseMsg):
            print("success")
            guard let resp = response,let products = response?.data else {
                return
            }
            if self.filter.page == 1 {
                self.products = []
            }
                if products.count > 0 {
                    self.products.append(contentsOf: products)
                    self.filter.page? += 1
                }
            self.delegate?.ProductListing(self, didSuccessProductListingDataWithMsg: nil)
            self.isInProgress = false
        }
    }
}

// Updated:

class ProductsDescription: Codable {
var data: [Product]?

enum CodingKeys: String, CodingKey {
    case data
}

required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        let dataJSON = try values.decodeIfPresent(JSONModel.self, forKey: .data)

            if let productsData = try dataJSON?.rawData() {
                self.data = try JSONDecoder().decode([Product].self, from: productsData)
            }

        }
}

Api response:

{
"page" : "1",
"data" : [
{
  "options" : [
    {
      "value" : "Black berries",
      "key" : 128
    }
  ],
  "product_name" : "Fresh",
  "old_price" : "$10.00",
  "prodt_name" : "Exotic Fruits",
  "is_favorite" : 1,
  "product_rating" : 0,
  "product_id" : "13",
  "user_id" : "135",
  "brand_id" : "126",
  "selprod_id" : "128",
  "product_veg_status" : "1",
  "user_name" : "raj yadav",
  "product_price" : "$10.00",
  "prodcat_id" : "211",
  "discounted_price" : "-0% Off",
  "product_name" : "Black berries",
  "special_price_found" : "0",
  "selprod_stock" : "1000",
  "selprod_min_order_qty" : "1",
  "product_model" : "b44"
},

Error:

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil)) 

In short problem is when response comes as below:

  "data" : [ 
            {

If comes this way, it works fine:

 "data": { 
          "products": [ 
iPhone 7
  • 1,731
  • 1
  • 27
  • 63
  • 2
    Full error message would be great. `Product` declaration would be nice too. – Larme Jun 17 '20 at 12:43
  • typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary but found an array instead.", underlyingError: nil)) – iPhone 7 Jun 17 '20 at 12:52
  • Product is the model class containing all the keys mention above in api response – iPhone 7 Jun 17 '20 at 12:53
  • What's the code of `makeAPIRequest(forAPI:`? Also, please edit your question with the full error message. It's harder to read into comment. – Larme Jun 17 '20 at 12:55
  • where does the decoding happen? Cant see the code for that. – Keshu R. Jun 17 '20 at 12:59
  • problems with this code : "data" : [ { If it's this way, it's working fine then "data": { "products": [ – iPhone 7 Jun 17 '20 at 13:01
  • @Larme just sending parameters in it, that's fine already checked. Updated the question for more clear understanding. Please have a look – iPhone 7 Jun 17 '20 at 13:08
  • Aaaaaah. Sometimes your API is responding `data: {}` and sometimes `data: []`... Use a custom `init(from decoder: Decoder)` to manage that. There should be a better duplicate question, but I found this one https://stackoverflow.com/questions/48739760/swift-4-json-codable-value-returned-is-sometimes-an-object-others-an-array – Larme Jun 17 '20 at 13:11
  • Does this answer your question? [Swift 4 JSON Codable - value returned is sometimes an object, others an array](https://stackoverflow.com/questions/48739760/swift-4-json-codable-value-returned-is-sometimes-an-object-others-an-array) – Jawad Ali Jun 17 '20 at 13:50
  • This should be better: https://stackoverflow.com/questions/47935705/using-codable-with-value-that-is-sometimes-an-int-and-other-times-a-string, in the `try? container.decode(Int.self, forKey: .id)`should be then `if let singleValue = try? container.decode(Data.self, forKey: .data) {self.data = [singleValue] } else {self.data = try container.decode([Data].self, forKey: .data) }` – Larme Jun 17 '20 at 14:01
  • Does this answer your question? [Using codable with value that is sometimes an Int and other times a String](https://stackoverflow.com/questions/47935705/using-codable-with-value-that-is-sometimes-an-int-and-other-times-a-string) – Larme Jun 17 '20 at 14:01
  • @Larme no, I am not clear, I have updated code as per some understanding that I got. Updated the question again please check – iPhone 7 Jun 17 '20 at 16:32
  • Could you show a real JSON of both possibilities, and what struct Product looks like ? Only the two different JSON and struct should be enough to reproduce your issue. The request doesn't seem needed for instance. – Larme Jun 17 '20 at 16:34
  • can you start separate room for details please – iPhone 7 Jun 17 '20 at 16:35
  • @Larme check updated question also – iPhone 7 Jun 17 '20 at 16:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/216151/discussion-between-iphone-7-and-larme). – iPhone 7 Jun 17 '20 at 17:18

0 Answers0