【问题标题】:Parse Json array without keys swift 4解析没有键的Json数组swift 4
【发布时间】:2019-08-05 12:55:53
【问题描述】:

我一直在解析 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。

【问题讨论】:

    标签: ios arrays json swift parsing


    【解决方案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"
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果您只需要底部的数据数组,则不需要将所有内容都放入解码的结构中。只需解码您想要的响应部分并从那里提取数据。此外,该数据数组并没有真正解析没有键的 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)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-08
        • 1970-01-01
        • 1970-01-01
        • 2018-05-31
        • 2018-08-15
        • 1970-01-01
        • 2023-03-16
        相关资源
        最近更新 更多