【问题标题】:How do I decode a JSON object whose attributes are stored as values in another attribute called "properties?"如何解码其属性作为值存储在另一个名为“属性”的属性中的 JSON 对象?
【发布时间】:2020-05-21 18:30:31
【问题描述】:

我正在从国家气象局获取天气预报。我得到了一个大致像这样的 JSON 对象(出于所有意图和目的):

{
  "properties":{
    "periods":[
      {
        "number":1,
        "name":"This Afternoon",
        "startTime":"2020-05-21T12:00:00-06:00",
        "endTime":"2020-05-21T18:00:00-06:00",
        "isDaytime":true,
        "temperature":58,
        "temperatureUnit":"F",
        "temperatureTrend":"falling",
        "windSpeed":"20 to 23 mph",
        "windDirection":"SW",
        "icon":"https://api.weather.gov/icons/land/day/rain,20",
        "shortForecast":"Slight Chance Light Rain",
        "detailedForecast":"A slight chance of rain. Partly sunny..."
      },
      {
        "number":2,
        "name":"Tonight",
        "startTime":"2020-05-21T18:00:00-06:00",
        "endTime":"2020-05-22T06:00:00-06:00",
        "isDaytime":false,
        "temperature":39,
        "temperatureUnit":"F",
        "temperatureTrend":"rising",
        "windSpeed":"7 to 20 mph",
        "windDirection":"S",
        "icon":"https://api.weather.gov/icons/land/night/rain,50/rain,80",
        "shortForecast":"Rain",
        "detailedForecast":"Rain. Mostly cloudy..."
      }
    ]
  }
}

我已经定义了一个 Swift 结构来存储预测:

struct WeatherForecast {
    var startTime : Date?
    var endTime : Date?
    var temperature : Int? // Degrees Fahrenheit.
    var temperatureTrend : String?
    var windSpeed : String? // Miles per hour
    var windDirection : String?
    var shortForecast : String?
    var detailedForecast : String?
    var iconPath : String?
}

如何解码“周期”部分,以便获得一组 WeatherForecast(又名 [WeatherForecast])?

【问题讨论】:

  • 最简单的方法是在链上定义可解码的数据类型:一个包含properties 键,另一个用于periods 键,例如struct Period: Decodable { let periods: [WeatherForecast] }。不要忘记让WeatherForecast 可解码
  • @NewDev 我犯了一个错误-应该只有一个“句点”属性,它的值是一个数组。
  • 好的 - 我编辑了你的问题来解决。但我所说的仍然存在

标签: json swift decodable


【解决方案1】:

最好的方法是将您的数据解码为CodableProperties 结构,然后为WeatherForecast 添加一个新的初始化程序,该初始化程序接受Period 作为参数并设置WeatherForecast 的属性。最后,在解码数据后,您可以将其映射到所需的weatherForecasts 数组中。

let properties = try? JSONDecoder().decode(Properties.self, from: data)
let weatherForecasts = properties.properties.periods.map { WeatherForecast(period: $0) }

extension WeatherForecast {
    init(period: Period) {
        startTime = period.startTime
        // ...

【讨论】:

  • JSON 对象还有一堆我不关心的数据。我的 Properties 结构是否也必须存储我不需要的信息,还是只能存储我实际需要的信息?
  • 您只需要拥有您需要的数据。你可以避免休息。
【解决方案2】:

最简单的方法是定义整齐地映射到这个 JSON 的所有数据类型:

struct WeatherProperties: Decodable {
  let periods: [WeatherForecast]
}

struct WeatherData: Decodable {
  let properties: WeatherProperties
}

然后你就可以解码WeatherData并得到[WeatherForecast]

let decoder = JSONDecoder()
let weatherData = try decoder.decode(WeatherData.self, jsonData)

let weatherForecasts = weatherData.properties.periods

不要忘记让您的WeatherForecast 符合Decodable。如果所有属性也都是可解码的,那么除了声明它符合之外,您无需做任何其他事情:

extension WeatherForecast: Decodable { }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-17
    • 2022-11-10
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    相关资源
    最近更新 更多