Home > OS >  Decoding 1957 Dictionaries from an array
Decoding 1957 Dictionaries from an array

Time:10-28

Goals

  1. Accessing the Dictionaries within an array
  2. Some how get all 1957 Dictionaries decoded without hand coding each ticker name.

The below image is data from enter image description here

With the help of another question which was answered here I have included code below which I am trying to change to accomplish the above goals.

CallApi.swift - this file calls the API and models it to PriceApiModel

import UIKit

class ViewController: UIViewController {
    
    let headers = [
        "X-RapidAPI-Key": "Sorry I cannot include this",
        "X-RapidAPI-Host": "binance43.p.rapidapi.com"
    ]

    let request = NSMutableURLRequest(url: NSURL(string: "https://binance43.p.rapidapi.com/ticker/price")! as URL,
                                            cachePolicy: .useProtocolCachePolicy,
                                        timeoutInterval: 10.0)
        

    func getData() {
        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers

        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
            if (error != nil) {
                print("error")
            } else {
                let httpResponse = response as? HTTPURLResponse
                do {
                    //let dictionary = try JSONSerialization.jsonObject(with: data!, options: [])
                    let model = try JSONDecoder().decode(PriceApiModel.self, from: data!)
                    
                    //print(String(model.symbol)   "name") // please see output below
                    //print(dictionary)
                } catch {
                    print("NOT WORKING ")
                }
            }
        })
        dataTask.resume()
        
    }
}

PriceApiModel.swift - I am trying to find a way for this file to be a model for decoding the data

struct PriceApiModel: Hashable, Codable {
    //changed the String type to Decimal
    var price: String

    // every property you are interested to decode needs a CodingKey.
    // You can omit values you are not interested in
    enum CodingKeys: CodingKey{
        case askPrice
    }
    
    // here you decode your data into the struct
    init(from decoder: Decoder) throws {
        // get the container
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // decode the askPrice into a String and cast it into a Decimal
        let askPrice = String(try container.decode(String.self, forKey: .askPrice))
        // check if casting was succesfull else throw
        guard let askPrice = askPrice else{
            throw CustomError.decodingError
        }
        // assign it
        self.askPrice = askPrice
    }
}

CodePudding user response:

So I just tried out what you want to achieve here. First of all, you declared a service class (fetching data) as ViewController, by inheritance a UIViewController. It seems to me a bit odd just having this in a class because the UIViewController is not used. Secondly, I would recommend you to watch or read something about Codable for example Hackingforswift. It helped at least me :)

However, here is a Code that shows you a way how it could work:

OptionalObject is needed because of the data structure, holding everything within an array.

struct OptionalObject<Base: Decodable>: Decodable {
    public let value: Base?

    public init(from decoder: Decoder) throws {
        do {
            let container = try decoder.singleValueContainer()
            self.value = try container.decode(Base.self)
        } catch {
            self.value = nil
        }
    }
}

struct PriceApiModel: Codable {
    let price: String
    let symbol: String
}
class Service {
    
    let headers = [
        "X-RapidAPI-Key": "",
        "X-RapidAPI-Host": "binance43.p.rapidapi.com"
    ]

    let request = NSMutableURLRequest(
        url: URL(string: "https://binance43.p.rapidapi.com/ticker/price")!,
        cachePolicy: .useProtocolCachePolicy,
        timeoutInterval: 5.0
    )
    
    init() {
        self.getData()
    }

    func getData() {
        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers

        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
            if let data = data {
                let model = try? JSONDecoder().decode([OptionalObject<PriceApiModel>].self, from: data)
                print(model?.compactMap { $0.value?.price })
                print(model?.compactMap { $0.value?.symbol })
            }
        })
        
        dataTask.resume()
    }
}

Hope I could help.

  • Related