如何在Swift中拆分JSON字符串?

时间:2019-12-10 18:50:17

标签: ios json swift xcode

我正在编写一个从Timezonedb API中提取数据以获取可用时区列表的应用程序:

https://timezonedb.com/references/list-time-zone

我正在尝试解析当前格式化为“欧洲/安道尔”的zoneName。我的问题是如何将JSON字符串拆分为仅在表格视图中显示城市名称(即“安道尔”)?

这是我得到的回复:

{
"status":"OK",
"message":"",
"zones":[
    {
        "countryCode":"AD",
        "countryName":"Andorra",
        "zoneName":"Europe\/Andorra",
        "gmtOffset":7200,
        "timestamp":1464453737
    },
    {
        "countryCode":"AE",
        "countryName":"United Arab Emirates",
        "zoneName":"Asia\/Dubai",
        "gmtOffset":14400,
        "timestamp":1464460937
    },
    {"
        countryCode":"AF",
        "countryName":"Afghanistan",
        "zoneName":"Asia\/Kabul",
        "gmtOffset":16200,
        "timestamp":1464462737
    }]}

这是我的代码:

型号:

struct TimeZones: Codable {
let status, message: String?
let zones: [Zone]?
}

struct Zone: Codable {
let countryCode, countryName, zoneName: String?
let gmtOffset, timestamp: Int?
}

这是网络代码:

var cities: [Zone] = []

   func getAvailableTimeZones() {

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    let url = Bundle.main.url(forResource: "data", withExtension: "json")!

    let task = session.dataTask(with: url) { data, response, error in

        // Check for errors
        guard error == nil else {
            print ("error: \(error!)")
            return
        }
        // Check that data has been returned
        guard let content = data else {
            print("No data")
            return
        }

        do {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            let timeZones = try decoder.decode(TimeZones.self, from: content)

            if let zones = timeZones.zones {
                self.cities.append(contentsOf: zones)
            }

        } catch let err {
            print("Err", err)
        }
    }
    // Execute the HTTP request
    task.resume()
}

TableViewController:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "searchResultsCell", for: indexPath)

    cell.textLabel?.text = cities[indexPath.row].zoneName

    return cell
}

任何帮助表示赞赏。谢谢。

2 个答案:

答案 0 :(得分:3)

一种解决方案是添加CodingKeys和一个计算属性。

并且没有理由将结构成员声明为可选

struct TimeZones: Decodable {
   let status, message: String 
   let zones: [Zone]
}

struct Zone: Decodable {
    let countryCode, countryName, zoneName: String
    let gmtOffset, timestamp: Int

    private enum CodingKeys: String, CodingKey { case countryCode, countryName, zoneName, gmtOffset, timestamp}

    lazy var zoneCountry : String = {
       return zoneName.components(separatedBy: "/").last!
    }()
}

并使用它

cell.textLabel?.text = cities[indexPath.row].zoneCountry

答案 1 :(得分:0)

要以最小的变化获得所需的输出,只需更新cellForRowAt()方法,如下所示:

let zoneName = cities[indexPath.row].zoneName.components(separatedBy: "/").last ?? ""
cell.textLabel?.text = zoneName