我坚持解析JSON
。结构真的很难。我正在尝试一种可解码的方法。
import UIKit
struct WeatherItem: Decodable {
let title: String?
let value: String?
let condition: String?
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("hello")
let jsonUrlString = "http://virtualflight.ddns.net/api/weather.php?icao=ehrd"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
var arr = [WeatherItem]()
do {
let res = try JSONDecoder().decode([String:[[String]]].self, from: data)
let content = res["title"]!
content.forEach {
if $0.count >= 3 {
arr.append(WeatherItem(title:$0[0],value:$0[1],condition:$0[2]))
}
}
print(arr)
} catch {
print(error)
}
}
}
}
以下是json:
{
"temperature": {
"value_c": 11,
"value_f": 285,
"condition": "Good",
"value_app": "11 \u00b0C (285 \u00b0F)"
},
"visibility": {
"value_km": 10,
"value_m": 6.2,
"condition": "Good",
"value_app": "10 KM (6.2 Mi)"
},
"pressure": {
"value_hg": 29.4,
"value_hpa": 996,
"condition": "Good",
"value_app": "29.4 inHg (996 hPa)"
},
"wind": {
"value_kts": 20,
"value_kmh": 37,
"value_heading": 280,
"condition": "Bad",
"value_app": "280\u00b0 at 20 KTS (37 Km\/H)"
},
"station": "EHRD",
"metar": "EHRD 141355Z AUTO 28020KT 250V320 9999 SCT038 BKN043 BKN048 11\/07 Q0996 NOSIG",
"remarks": "NOSIG",
"weather_page_ios_simple": [
[
"Temperature",
"11 \u00b0C (285 \u00b0F)",
"Good"
],
[
"Visibility",
"10 KM (6.2 Mi)",
"Good"
],
[
"Pressure",
"29.4 inHg (996 hPa)",
"Good"
],
[
"Wind",
"280\u00b0 at 20 KTS (37 Km\/H)",
"Bad"
],
[
"Metar",
"EHRD 141355Z AUTO 28020KT 250V320 9999 SCT038 BKN043 BKN048 11\/07 Q0996 NOSIG",
"Unknown"
],
[
"Remarks",
"NOSIG",
"Unknown"
],
[
"Station",
"EHRD",
"Unknown"
],
[
"UICell",
"iOS 12",
"siri_weather_cell"
]
]
}
任何想法如何做到这一点?我只需要最后一个数组weather_page_ios_simple。
答案 0 :(得分:1)
看看https://app.quicktype.io,它将为您提供JSON的数据结构。
import Foundation
struct Welcome: Codable {
let temperature: Temperature
let visibility: Visibility
let pressure: Pressure
let wind: Wind
let station, metar, remarks: String
let weatherPageIosSimple: [[String]]
enum CodingKeys: String, CodingKey {
case temperature, visibility, pressure, wind, station, metar, remarks
case weatherPageIosSimple = "weather_page_ios_simple"
}
}
struct Pressure: Codable {
let valueHg: Double
let valueHpa: Int
let condition, valueApp: String
enum CodingKeys: String, CodingKey {
case valueHg = "value_hg"
case valueHpa = "value_hpa"
case condition
case valueApp = "value_app"
}
}
struct Temperature: Codable {
let valueC, valueF: Int
let condition, valueApp: String
enum CodingKeys: String, CodingKey {
case valueC = "value_c"
case valueF = "value_f"
case condition
case valueApp = "value_app"
}
}
struct Visibility: Codable {
let valueKM: Int
let valueM: Double
let condition, valueApp: String
enum CodingKeys: String, CodingKey {
case valueKM = "value_km"
case valueM = "value_m"
case condition
case valueApp = "value_app"
}
}
struct Wind: Codable {
let valueKts, valueKmh, valueHeading: Int
let condition, valueApp: String
enum CodingKeys: String, CodingKey {
case valueKts = "value_kts"
case valueKmh = "value_kmh"
case valueHeading = "value_heading"
case condition
case valueApp = "value_app"
}
}
答案 1 :(得分:0)
如果仅需要底部数据数组,则无需将所有内容都放入解码后的结构中。只需解码所需的响应部分,然后从那里提取数据即可。此外,该数据数组实际上不是在没有键的情况下解析JSON。它只是一个字符串数组,您必须依靠这样的事实,即索引0始终是标题,索引1始终是值,索引2始终是条件。只是做一些验证,以确保它符合您的需求。像这样(未测试)
struct WeatherItem {
let title: String?
let value: String?
let condition: String?
init(title: String?, value: String?, condition: String?) {
self.title = title
self.value = value
self.condition = condition
}
}
struct WeatherResponse: Decodable {
var weatherItems: [WeatherItem]
private enum CodingKeys: String, CodingKey {
case weatherItems = "weather_page_ios_simple"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let weatherItemArrays = try container.decode([[String]].self, forKey: .weatherItems)
weatherItems = []
for weatherItemArray in weatherItemArrays {
var title: String?
if weatherItemArray.count > 0 {
title = weatherItemArray[0]
}
var value: String?
if weatherItemArray.count > 1 {
value = weatherItemArray[1]
}
var condition: String?
if weatherItemArray.count > 2 {
condition = weatherItemArray[2]
}
weatherItems.append(WeatherItem(title: title, value: value, condition: condition))
}
}
}
然后,当您获得api响应时,请使用类似的内容
do {
let weatherResponse = try JSONDecoder().decode(WeatherResponse.self, from: <YOUR API RESPONSE DATA>)
let weatherItems = weatherResponse.weatherItems
<DO WHATEVER YOU WANT WITH THE WEATHER ITEMS>
} catch let error {
print(error)
}