JSON数组中的数组解析,SWIFTYJson

3
我一直在学习如何在SWIFT应用程序中解析JSON。到目前为止,我一直使用简单的免费API,并没有出现任何问题,应用程序运行得很好。 但是现在我正在调用返回一个数组的API,而且这个数组还嵌套了一个数组。 我已经阅读并准备好了变量来访问指定元素,但是SWIFT仍然看不到这个返回的JSON中的任何数据。我已经苦苦挣扎了两天,尝试了所有可以在线找到和想到的方法,但是我的默认变量仍未被JSON中的数据覆盖。 我使用了SWIFTYJson库。
JSON部分提取:
    {
  "list" : [
    {
      "main" : {
        "grnd_level" : 984.67999999999995,
        "temp_min" : 283.30000000000001,
        "temp_max" : 284.54599999999999,
        "temp" : 283.30000000000001,
        "sea_level" : 1022.5,
        "pressure" : 984.67999999999995,
        "humidity" : 88,
        "temp_kf" : -1.25
      },
      "clouds" : {
        "all" : 0
      },
      "weather" : [
        {
          "main" : "Clear",
          "icon" : "01n",
          "description" : "clear sky",
          "id" : 800
        }
      ],

处理它的代码:

func getWeatherData(url: String, parameters: [String : String]){
    //make http request and handle the JSON response
    print("\(url)\(parameters)")
    Alamofire.request(url, method: .get, parameters: parameters).responseJSON {
        response in //in means you are inside a closure (function inside a function)
        if response.result.isSuccess {
            print("Successfully got the weather data!")

            let weatherJSON : JSON = JSON(response.result.value!) //saving the JSON response to a constant weathrJSON  . We are using ! to self unwrap the value.
            self.updateWeatherData(json: weatherJSON) //func to parse our json from API. Self tells the compiler to look for the method inside the current class

            print(weatherJSON)
        } else {
            self.cityName.text = "Unable to fetch weather - please check active connection."
        }

    }
}

func updateWeatherData(json: JSON) {
            (...)
             //parse JSON for weather forecast day 1
            weatherDataModel.weatherTest1 = json["list"][0]["weather"][0]["id"].intValue

            //parse JSON for weather forecast day 2
            weatherDataModel.weatherTest2 = json["list"][8]["weather"][0]["id"].intValue

            //parse JSON for weather forecast day 3
            weatherDataModel.weatherTest3 = json["list"][16]["weather"][0]["id"].intValue

            print("TEST variable 1: \(weatherDataModel.weatherTest1)")
            print("TEST variable 2: \(weatherDataModel.weatherTest2)")
            print("TEST variable 3: \(weatherDataModel.weatherTest3)")

在控制台打印的变量值仍然保持默认值不变:

TEST variable 1: 0
TEST variable 2: 0
TEST variable 3: 0
3个回答

1
你用错误的方法解析数据。 json["list"]只是JSON对象,不是数组对象,那么你怎么能使用[0]来传递索引呢。
应该按以下解决方案进行更正。
weatherDataModel.weatherTest1 = json["list"].arrayValue[0]["weather"].arrayValue[0]["id"].intValue

使用上述代码,我的应用程序目前崩溃了,线程1:致命错误:数组越界。我会进一步调查,谢谢。 - M.Spoldi
@M.Spoldi 这种情况可能是因为您的数组没有值,您可以使用安全检查索引。 - Jaydeep Vora

0
在当前版本的SwiftyJSON中,您正在使用的初始化器上的注释如下:
/**
 Creates a JSON object
 - note: this does not parse a `String` into JSON, instead use `init(parseJSON: String)`

 - parameter object: the object

 - returns: the created JSON object
 */

所以,你应该使用let weatherJSON : JSON = JSON(parseJSON: response.result.value!)而不是let weatherJSON : JSON = JSON(response.result.value!)

之后,我认为你的当前代码应该可以工作,基于你的JSON。

编辑

我知道选择了另一个答案,它说json["list"]是一个JSON对象而不是数组,但是摘录中指示的JSON清楚地表明:

"list" : [
    {

[是一个数组的标识,所以我不确定最初出了什么问题。我将保留这个答案,以防有人使用init(JSON)解析当前版本的SwiftyJSON中的对象时遇到相同的问题。


0

如果你正在学习如何在Swift中解析,那么你必须学会如何构建一个模型来正确解析你的JSON。

(顺便说一句,如果你使用的是Swift 4,就不需要使用SWIFTYJson了,可以在这里了解更多信息:https://benscheirman.com/2017/06/swift-json/

如果你想使用SWIFTYJson,这是一个例子:

struct WeatherDataModel {
    var list = [ListModel]?

    init() {
        self.list = []
    }

    init(json: [String: Any]) {
        if let object = json["list"] as? [[String: Any]] {
            for listJson in object {
                let list = ListModel(json: listJson)
                self.list.append(list)
            }
        }
    }
}

struct ListModel {
    var main : Main?
    var clouds : Clouds?
    var weather : [Weather]?
    init() {
        self.main = Main()
        self.clouds = Clouds()
        self.weather = []
    }
    init(json: [String: Any]) {
        if let mainJson = json["main"] as? [String: Any] {
            self.main = MainModel(json: mainJson)
        }
        if let cloudsJson = json["clouds"] as? [String: Any] {
            self.clouds = CloudsModel(json: cloudsJson)
        }
        if let objectWeather = json["weather"] as? [[String: Any]] {
            for weatherJson in objectWeather {
                let weather = WeatherModel(json: weatherJson)
                self.weather.append(weather)
            }
        }
    }
}

对于MainModel、CloudsModel和WeatherModel也要做同样的操作。

当你获取到所有的模型后,可以在请求中进行解析:

Alamofire.request(url, method: .get, parameters: parameters).validate().responseJSON { (response) -> Void in
        if let value = response.data {
            do {
                let json = try JSON(data: data)
                if let dictionnary = json.dictionnaryObject {
                    let object = WeatherDataModel(json: dictionnary)
                    self.updateWeatherData(data: object)
                }
            } catch {
                print("cannot convert to Json")
            }
        }
 }

然后你会发现在你的方法中,数据对象已经被解析:

func updateWeatherData(data: WeatherDataModel) {
    // exemple
    print(data.list[0].weather[0].id) // = 800
}

希望这能对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接