Swift 5 从 https 请求中解析 Json 数据
Swift 5 Parse Json data from https request
我正在尝试解析 json 并获取 “价格” 值。我如何解析 json 以在 swift 5 编程语言中实现此目的。我已经尝试过 codable struct,但我总是得到一个空结果。
JSON
{
"status" : "success",
"data" : {
"network" : "DOGE",
"prices" : [
{
"price" : "0.37981",
"price_base" : "USD",
"exchange" : "binance",
"time" : 1620014229
}
]
}
}
Swift
func api()
guard let url = URL(string: "https://sochain.com//api/v2/get_price/DOGE/USD") else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
let dataString = String(data: data, encoding: .utf8)
}
task.resume()
}
为您的 JSONDecoder
使用 .convertFromSnakeCase
func fetch(callback: @escaping (Result<DataPrice, Error>)->Void) {
guard let url = URL(string: "https://sochain.com//api/v2/get_price/DOGE/USD") else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
if let error = error {
callback(.failure(error))
}
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(DataPrice.self, from: data)
callback(.success(result))
} catch {
callback(.failure(error))
}
}.resume()
}
你的模型应该看起来像
struct DataPrice: Decodable {
var data : Prices
}
struct Prices: Decodable {
var prices: [Price]
}
struct Price: Decodable {
var price : String
var priceBase: String
var exchange: String
var time: Int
}
你需要做的。
将responsedata
转换为json
阅读你得到的甲酸盐(在这里你会得到字典)
guard let url = URL(string: "https://sochain.com//api/v2/get_price/DOGE/USD") else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
do {
// make sure this JSON is in the format we expect
// convert data to json
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
// try to read out a dictionary
print(json)
if let data = json["data"] as? [String:Any] {
print(data)
if let prices = data["prices"] as? [[String:Any]] {
print(prices)
let dict = prices[0]
print(dict)
if let price = dict["price"] as? String{
print(price)
}
}
}
}
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
}
task.resume()
设置您的结构并展开常量以防止应用程序崩溃:
struct DataPrice: Decodable {
let data: Prices?
}
struct Prices: Decodable {
let prices: [MyPrice]?
let network: String?
}
struct MyPrice: Decodable {
let price: String?
let price_base: String?
let exchange: String?
let time: Double?
}
现在在控制器中设置 tableView 并添加 UITableViewDelegate 和 UITableViewDataSource 以显示结果:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
var productList = [MyPrice]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.backgroundColor = .darkGray
tableView.register(PriceCell.self, forCellReuseIdentifier: "cellId") //register your cell
view.addSubview(tableView)
tableView.frame = view.bounds
//this is the call to fetch objects
fetchObjects(urlString: "https://sochain.com//api/v2/get_price/DOGE/USD")
}
之后写给你 json 解码器函数:
fileprivate func fetchObjects(urlString: String) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { data, response, err in
guard let data = data, err == nil else { return }
do {
let jsonData = try JSONDecoder().decode(DataPrice.self, from: data)
self.productList = jsonData.data?.prices ?? [] //append data to your productLis array
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let jsonErr {
print("failed to decode json:", jsonErr)
}
}.resume() // don't forget
}
设置您的表格视图:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! PriceCell
let json = productList[indexPath.row]
cell.labelPrice.text = "Price: \(json.price_base ?? "")"
cell.labelPriceBase.text = "Price Base: \(json.price ?? "")"
cell.labelExchange.text = "Exchang: \(json.exchange ?? "")"
cell.labelTime.text = "Time: \(json.time ?? 0)"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 144
}
这是您的 tableView 自定义单元格:
class PriceCell: UITableViewCell {
let labelPrice: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
let labelPriceBase: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
let labelExchange: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
let labelTime: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.backgroundColor = .white
let stackView = UIStackView(arrangedSubviews: [labelPrice, labelPriceBase, labelExchange, labelTime])
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stackView)
stackView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
这是结果:
我正在尝试解析 json 并获取 “价格” 值。我如何解析 json 以在 swift 5 编程语言中实现此目的。我已经尝试过 codable struct,但我总是得到一个空结果。
JSON
{
"status" : "success",
"data" : {
"network" : "DOGE",
"prices" : [
{
"price" : "0.37981",
"price_base" : "USD",
"exchange" : "binance",
"time" : 1620014229
}
]
}
}
Swift
func api()
guard let url = URL(string: "https://sochain.com//api/v2/get_price/DOGE/USD") else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
let dataString = String(data: data, encoding: .utf8)
}
task.resume()
}
为您的 JSONDecoder
.convertFromSnakeCase
func fetch(callback: @escaping (Result<DataPrice, Error>)->Void) {
guard let url = URL(string: "https://sochain.com//api/v2/get_price/DOGE/USD") else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
if let error = error {
callback(.failure(error))
}
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(DataPrice.self, from: data)
callback(.success(result))
} catch {
callback(.failure(error))
}
}.resume()
}
你的模型应该看起来像
struct DataPrice: Decodable {
var data : Prices
}
struct Prices: Decodable {
var prices: [Price]
}
struct Price: Decodable {
var price : String
var priceBase: String
var exchange: String
var time: Int
}
你需要做的。
将
responsedata
转换为json
阅读你得到的甲酸盐(在这里你会得到字典)
guard let url = URL(string: "https://sochain.com//api/v2/get_price/DOGE/USD") else { return } let task = URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { return } do { // make sure this JSON is in the format we expect // convert data to json if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { // try to read out a dictionary print(json) if let data = json["data"] as? [String:Any] { print(data) if let prices = data["prices"] as? [[String:Any]] { print(prices) let dict = prices[0] print(dict) if let price = dict["price"] as? String{ print(price) } } } } } catch let error as NSError { print("Failed to load: \(error.localizedDescription)") } } task.resume()
设置您的结构并展开常量以防止应用程序崩溃:
struct DataPrice: Decodable {
let data: Prices?
}
struct Prices: Decodable {
let prices: [MyPrice]?
let network: String?
}
struct MyPrice: Decodable {
let price: String?
let price_base: String?
let exchange: String?
let time: Double?
}
现在在控制器中设置 tableView 并添加 UITableViewDelegate 和 UITableViewDataSource 以显示结果:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
var productList = [MyPrice]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.backgroundColor = .darkGray
tableView.register(PriceCell.self, forCellReuseIdentifier: "cellId") //register your cell
view.addSubview(tableView)
tableView.frame = view.bounds
//this is the call to fetch objects
fetchObjects(urlString: "https://sochain.com//api/v2/get_price/DOGE/USD")
}
之后写给你 json 解码器函数:
fileprivate func fetchObjects(urlString: String) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { data, response, err in
guard let data = data, err == nil else { return }
do {
let jsonData = try JSONDecoder().decode(DataPrice.self, from: data)
self.productList = jsonData.data?.prices ?? [] //append data to your productLis array
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let jsonErr {
print("failed to decode json:", jsonErr)
}
}.resume() // don't forget
}
设置您的表格视图:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! PriceCell
let json = productList[indexPath.row]
cell.labelPrice.text = "Price: \(json.price_base ?? "")"
cell.labelPriceBase.text = "Price Base: \(json.price ?? "")"
cell.labelExchange.text = "Exchang: \(json.exchange ?? "")"
cell.labelTime.text = "Time: \(json.time ?? 0)"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 144
}
这是您的 tableView 自定义单元格:
class PriceCell: UITableViewCell {
let labelPrice: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
let labelPriceBase: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
let labelExchange: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
let labelTime: UILabel = {
let label = UILabel()
label.text = ""
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0
label.textColor = .black
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.backgroundColor = .white
let stackView = UIStackView(arrangedSubviews: [labelPrice, labelPriceBase, labelExchange, labelTime])
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stackView)
stackView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
这是结果: