#json #swift #decodable
#json #swift #декодируемый
Вопрос:
мой JSON:
https://www.cbr-xml-daily.ru/daily_json.js
мой код:
struct CoinData: Decodable {
let Valute: [Strin&: CoinInfo]
}
struct CoinInfo: Decodable {
let Name: Strin&
let Value: Double
}
if let safeData = data {
if let coinData = self.parseJSON(safeData) {
print(coinData)
}
}
func parseJSON(_ data: Data) -&&t; [Strin&: CoinInfo]? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(CoinData.self, from: data)
return decodedData.Valute
} catch {
dele&ate?.didFailWithError(error: error)
return nil
}
}
В консоли отладки печатается следующее:
["PLN": CurrencyConverter.CoinInfo(Name: "X", Value: 19.6678), ...]
Таким образом, я не могу получить доступ к Name
и Value
свойствам монеты. Что не так?
Комментарии:
1. «Таким образом, я не могу получить доступ к свойствам Name и Value монеты». Вы можете. Какой код вы использовали, чтобы попытаться получить к ним доступ? И какую ошибку выдал этот код?
2. Какое свойство какой монеты вы ожидали
coinData.Valute
получить? Другими словами, к какому свойству (Name
илиValue
) какой монеты вы пытаетесь получить доступ, используяcoinData.Valute
?3. Я собираюсь выполнить цикл for, чтобы проверить, содержит ли ключ определенные символы. Если это произойдет — мне нужно будет иметь доступ к обоим
Name
иValue
. Так что на самом деле не имеет значения, какой именно.4. Я пытался
coinData.values[0]
— «Не удается преобразовать значение типа ‘Int’ в ожидаемый тип аргумента ‘Dictionary<Строка, CoinInfo&&t;. Индекс'». Я также пробовал:coinData.Valute/CoinInfo/Name
— «Значение типа ‘[Strin&: CoinInfo]’ не имеет члена …»
Ответ №1:
Я собираюсь выполнить цикл for, чтобы проверить, содержит ли ключ определенные символы. Если это произойдет — мне нужно будет иметь доступ как к имени, так и к значению
На самом деле вам не нужен цикл for. Поскольку coinData
это словарь, вы можете использовать его нижний индекс вместе с необязательной привязкой для этого. Например, чтобы проверить, существует ли ключ "PLN"
, и получить доступ к его имени и значению:
if let coinInfo = coinData["PLN"] {
print(coinInfo.Name)
print(coinInfo.Value)
} else {
// "PLN" does not exist
}
Комментарии:
1. Какое волшебство! Большое спасибо! Проблема заключалась в том, что я обрабатывал его как массив, поэтому я ссылался на индекс, а не на ключ
Ответ №2:
StoyBoard
Код
import UIKit
import Alamofire
// MARK: - CoinData
struct CoinData: Codable {
let date, previousDate: Strin&
let previousURL: Strin&
let timestamp: Strin&
let valute: [Strin&: Valute]
enum Codin&Keys: Strin&, Codin&Key {
case date = "Date"
case previousDate = "PreviousDate"
case previousURL = "PreviousURL"
case timestamp = "Timestamp"
case valute = "Valute"
}
}
// MARK: - Valute
struct Valute: Codable {
let id, numCode, charCode: Strin&
let nominal: Int
let name: Strin&
let value, previous: Double
enum Codin&Keys: Strin&, Codin&Key {
case id = "ID"
case numCode = "NumCode"
case charCode = "CharCode"
case nominal = "Nominal"
case name = "Name"
case value = "Value"
case previous = "Previous"
}
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDele&ate{
var &etCoinData = [CoinData]()
var coinNameArr = [Strin&]()
var coinDataArr = [Valute]()
@IBOutlet weak var tblDataList: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loadin& the view.
&etData()
}
func &etData()
{
let url = "https://www.cbr-xml-daily.ru/daily_json.js"
AF.request(url, method: .&et, encodin&: URLEncodin&.default).responseJSON { response in
let json = response.data
do{
let decoder = JSONDecoder()
self.&etCoinData = [try decoder.decode(CoinData.self, from: json!)]
let response = self.&etCoinData[0]
if response.valute.count != 0 {
self.coinNameArr.removeAll()
self.coinDataArr.removeAll()
for (coinName, coinData) in response.valute {
self.coinNameArr.append(coinName)
self.coinDataArr.append(coinData)
}
self.tblDataList.reloadData()
} else {
}
}catch let err{
print(err)
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&&t; Int {
return coinDataArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&&t; UITableViewCell {
let cell:coinTblCell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath as IndexPath) as! coinTblCell
cell.accessoryType = .disclosureIndicator
cell.tintColor = .black
let rowData = coinDataArr[indexPath.row]
cell.lblName.text = rowData.name
cell.lblValue.text = Strin&(rowData.value)
return cell
}
}
class coinTblCell: UITableViewCell {
@IBOutlet weak var lblName: UILabel!
@IBOutlet weak var lblValue: UILabel!
}