简体   繁体   English

Swift 5 解析来自 https 请求的 Json 数据

[英]Swift 5 Parse Json data from https request

I am trying to parse a json and get the "price" value.我正在尝试解析 json 并获取“价格”值。 How can I parse the json to achieve this in the swift 5 programming language.如何在 swift 5 编程语言中解析 json 以实现此目的。 I have tried codable struct but I keep getting a null result.我尝试了可编码结构,但我不断得到 null 结果。

JSON JSON

{
  "status" : "success",
  "data" : {
    "network" : "DOGE",
    "prices" : [
      {
        "price" : "0.37981",
        "price_base" : "USD",
        "exchange" : "binance",
        "time" : 1620014229
      }
    ]
  }
}

Swift 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()

}

Use .convertFromSnakeCase for your JSONDecoder为您的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()
            
    }

And your Model should look like你的 Model 应该看起来像

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
}

you need to do.你需要做。

  1. convert responsedata to jsonresponsedata数据转换为json

  2. read the formate(Here you will get dictionary) which you get.阅读你得到的甲酸盐(在这里你会得到字典)。

     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()

Set your structs and unwrap constant to prevent app crash:设置您的结构并展开常量以防止应用程序崩溃:

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?
}

now set tableView in your controller and add it UITableViewDelegate and UITableViewDataSource to display results:现在在 controller 中设置 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")
}

after that write you json decoder func:之后写你 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
}

set your tableView:设置你的表视图:

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
}

and this is your tableView custom cell:这是您的 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")
 }
}

This is the result:这是结果:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM