-1

I have an issue here... I am using WooCommerce API to get data from database... Everything is great with this code but i have a weird issue with getting Featured photo (featured_src), The featured photo Value is a String when the image of product exists, but when ever there is no image for the product, i get a bool value instead of a string( i get a false). And the app crashes. As you see in my code i specify the properties as String or int or.... and i set featured_src as string but sometimes i get a bool value for it. How should i edit my code?

import UIKit

struct Products: Decodable {
let products: [product]
}

struct product: Decodable {

let title: String
let id: Int
let price: String
let sale_price: String?
let featured_src: String?
let short_description: String
 }


class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    let jsonUrlString = "https://www.komeil24.com/wc-api/v3/products"

    guard let url = URL(string: jsonUrlString) else {return}

    URLSession.shared.dataTask(with: url) { (data, response, error) in

        guard let data = data else {return}

        do {

            let products = try JSONDecoder().decode(Products.self, from: data)
            print(products.products)

        } catch let jsonErr {

          print("Error" , jsonErr)
        }

    }.resume()

}

}

1 Answers1

0

The server encoded this terribly. But as developers, we must work with what we are given. You will have to decode Product manually. Also, I think feature_src is closer to a URL? instead of a String? (you can change that if you want).

The key takeaway here is instead of using try decoder.decode(URL.self, ...) and get an error if the key doesn't contain a URL, you use try? decoder.decode(URL.self, ...) and get a nil.

struct Product: Decodable {
    let title: String
    let id: Int
    let price: String
    let salePrice: String?
    let featuredSource: URL?
    let shortDescription: String

    private enum CodingKeys: String, CodingKey {
        case title, id, price
        case salePrice = "sale_price"
        case featuredSource = "featured_src"
        case shortDescription = "short_description"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        // Nothing special here, just typical manual decoding
        title            = try container.decode(String.self, forKey: .title)
        id               = try container.decode(Int.self, forKey: .id)
        price            = try container.decode(String.self, forKey: .price)
        salePrice        = try container.decodeIfPresent(String.self, forKey: .salePrice)
        shortDescription = try container.decode(String.self, forKey: .shortDescription)

        // Notice that we use try? instead of try
        featuredSource   = try? container.decode(URL.self, forKey: .featuredSource)
    }
}
Code Different
  • 90,614
  • 16
  • 144
  • 163