Summary
I am attempting to get data from an API and decode it into a json
I have 2 questions about the below code
is the output from apiOutput variable suitable to decode into a json format if not how do I get the correct output? I am thinking it might be changing the options in
JSONSerialization.jsonObject
how do I feed my
apiOutput
variable to my PriceApiModel.swift which I am hoping is capable of decoding apiOutput into the correct json format. Even if PriceApiModel.swift is able to do this I am unsure how to feed apiOutput into it
This image is of the data the API is returning
My attempt at getting to the API data after its been called please see full code below
// from AppDelegate.swift full file included below
let apiOutput = try JSONSerialization.jsonObject(with: data!, options: [])
print(apiOutput) // please see output below
Output from printing apiOutput
{
askPrice = "0.07530300";
askQty = "28.15780000";
bidPrice = "0.07530200";
bidQty = "20.99700000";
closeTime = 1666814307216;
count = 389744;
firstId = 383543634;
highPrice = "0.07593900";
lastId = 383933377;
lastPrice = "0.07530300";
lastQty = "11.85740000";
lowPrice = "0.07230700";
openPrice = "0.07365100";
openTime = 1666727907216;
prevClosePrice = "0.07365200";
priceChange = "0.00165200";
priceChangePercent = "2.243";
quoteVolume = "13084.96427533";
symbol = ETHBTC;
volume = "176432.41160000";
weightedAvgPrice = "0.07416418";
}
I have made PriceApiModel.swift to try and decode the above output. However do not believe I have the right options in JSONSerialization because the output looks more like variables than a json file.
// PriceApiModel.swift
import Foundation
import SwiftUI
import CoreLocation
struct PriceApiModel: Hashable, Codable {
var askPrice: String
var askQty: String
var bidPrice: String
var bidQty: String
var closeTime: Int
var count: Int
var firstId: Int
var highPrice: String
var lastId: Int
var lastPrice: String
var lastQty: String
var lowPrice: String
var openPrice: String
var openTime: Int
var prevClosePrice: String
var priceChange: String
var priceChangePercent: String
var quoteVolume: String
var symbol: String
var volume: String
var weightedAvgPrice: String
}
Full code of AppDelegate.swift
import UIKit
class ViewController: UIViewController {
let headers = [
"X-RapidAPI-Key": "cannot provide this please see sample outpout",
"X-RapidAPI-Host": "binance43.p.rapidapi.com"
]
let request = NSMutableURLRequest(url: NSURL(string: "https://binance43.p.rapidapi.com/ticker/24hr?symbol=ETHBTC")! 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 apiOutput = try JSONSerialization.jsonObject(with: data!, options: [])
print(apiOutput) // this is the output I am getting
} catch {
print("NOT WORKING ")
}
}
})
dataTask.resume()
}
}
CodePudding user response:
If you just want to decode the received data into your model you can use a JSONDecoder
.
let model = try JSONDecoder().decode(PriceApiModel.self, from: data!)
But if you want to use this model further on in your code I would recommend using some usefull types for the data you recieve. I made an example for askPrice
but the others would be done in a similar way.
// used for throwing errors
enum CustomError: Error{
case decodingError
}
struct PriceApiModel: Hashable, Codable {
//changed the String type to Decimal
var askPrice: Decimal
var askQty: String
var bidPrice: String
var bidQty: String
var closeTime: Int
var count: Int
var firstId: Int
var highPrice: String
var lastId: Int
var lastPrice: String
var lastQty: String
var lowPrice: String
var openPrice: String
var openTime: Int
var prevClosePrice: String
var priceChange: String
var priceChangePercent: String
var quoteVolume: String
var symbol: String
var volume: String
var weightedAvgPrice: 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 = Decimal(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
}
}