如何在swift 3中获取给定Json响应的计数?

时间:2017-08-21 09:19:39

标签: ios swift3

在api中我得到以下数据,在这里我需要得到所有数组中的总名数

{
  "Flat": [
    {
      "price": "$5.00", 
      "id": 11, 
      "name": "Fixed"
    }
  ], 
  "United Parcel Service": [
    {
      "price": "$109.12", 
      "id": 1, 
      "name": "worldwide Expedited"
    }, 
    {
      "price": "$120.18", 
      "id": 2, 
      "name": "worldwide Express saver"
    }
  ]
}

我尝试了以下代码来获取所有数组中的名称数

    var arrayss =  [String:AnyObject]()
    var keys = [String]()
    let urlString = "http://www.json-generator.com/api/json/get/bVgbyVQGmq?indent=2"
    var totalCount = 0
func shippingmethodURL() {
        let url = NSURL(string: self.urlString)
        URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
            if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
                self.arrayss = jsonObj as! [String : AnyObject]
                self.keys = jsonObj?.allKeys as! [String]
                OperationQueue.main.addOperation({
                    self.shippingTableView.reloadData()
                    let sectionHeight = self.arrayss.count * 31
                    let cellHeight = self.keys.count * 44
                    self.shippingHeightConstraint.constant = CGFloat(sectionHeight + cellHeight)
                    self.heightConstant = Int(self.shippingHeightConstraint.constant)
                    self.delegate?.heightConstant(int: self.heightConstant!)
                })
            }
        }).resume()
    }

2 个答案:

答案 0 :(得分:0)

首先,当它们具有原生的Swift等价物时(例如FoundationNSURL),请不要使用NSDictionary数据类型。

除此之外,你的问题是你在计算字典的键。但是,您要做的是遍历您的字典,使用条件转换检查与该键关联的值是否为数组,如果它是一个数组,请检查该数组的字典元素是否具有“name “键,如果有,则增加计数,否则什么也不做。

在解析JSON数据时也不要使用强制解包和强制转换,因为在网络响应中,这些可能会失败并且您的应用程序会崩溃。

func shippingmethodURL() {
    guard let url = URL(string: self.urlString) else {return}
    URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) -> Void in
        if let data = data, let jsonObj = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String:AnyObject] {
            self.arrayss = jsonObj
            self.keys = Array(jsonObj.keys)

            var totalCount = 0
            for value in jsonObj.values {
                if let array = value as? [[String:Any]] {
                    for element in array {
                        if let name = element["name"] as? String {
                            totalCount += 1
                        }
                    }
                }
            }
            //update UI and other variables here
        }
    }).resume()
}

答案 1 :(得分:0)

正如在其他答案中所建议的那样,您应该始终考虑除NS前缀之外的原生Swift类型(即NSDictionaryNSURL)。因此,您应该将原生Swift类型用作DictionaryURL。另一件事是 最好使用Any以外的AnyObject 。你可以看看here为什么我这么说。

说得够,你应该看看:

var arrayss = [String:Any]()
var keys = [String]()
let urlString = "http://www.json-generator.com/api/json/get/bVgbyVQGmq?indent=2"
var nameKeyCount = 0

func shippingmethodURL() {
    guard let url = URL(string: self.urlString) else {return}
    URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) -> Void in
        if let data = data, let jsonObj = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String:Any] {
            self.arrayss = jsonObj
            self.keys = Array(jsonObj.keys)
            // Now you want to know the count for `name` key
            // Below is the standard way in swift.
            // Looping through each of the object is cumbersome
            self.nameKeyCount = jsonObj.flatMap { $0.value.flatMap { $0.filter { $0.key == "name" } } }.count

            // As URLSession's data task is an asynchronous task and done in a thread other than main thread, you should have your main thread to update any UI related thing
            Dispatch.main.async {
                // update UI here
            }
        }
    }).resume()
}