我如何能够确保 json 元素不为零?

Posted

技术标签:

【中文标题】我如何能够确保 json 元素不为零?【英文标题】:How would I be able to ensure json elements are not nil? 【发布时间】:2016-09-01 21:27:07 【问题描述】:

我尝试在我的代码中使用可选绑定,但是当我执行和调试时它仍然显示为 nil,所以我想知道我是否使用了不正确的方法?

Here is the code which shows me trying to parse my JSON

这是我用来尝试解析 JSON 的代码:

import Foundation

protocol ListingModelProtocol: class 
    func itemsDownloaded(items: NSArray)



class ListingModel: NSObject, NSURLSessionDataDelegate 

    weak var delegate: ListingModelProtocol!

    var data : NSMutableData = NSMutableData()

    let urlPath: String = "http://booksmart.hol.es/service.php" // this will be changed to the path where service.php lives


    func downloadItems() 

        let url: NSURL = NSURL(string: urlPath)!
        var session: NSURLSession!
        let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()


        session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)

        let task = session.dataTaskWithURL(url)

        task.resume()

    

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) 
        self.data.appendData(data);

    

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) 
        if error != nil 
            print("Failed to download data")
        else 
            print("Data downloaded")
            self.parseJSON()
        



    
    func parseJSON() 

        var jsonResult: NSMutableArray = NSMutableArray()

        do
            jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray

         catch let error as NSError 
            print(error)

        

        var jsonElement: NSDictionary = NSDictionary()
        let properties: NSMutableArray = NSMutableArray()

        for(var i = 0; i < jsonResult.count; i+=1)
        

            jsonElement = jsonResult[i] as! NSDictionary

            let property = PropertyModel()

            //the following insures none of the JsonElement values are nil through optional binding
            if let propertyType = jsonElement["Property Type"] as? String,
                let price = jsonElement["Price"] as? String,
                let distance = jsonElement["Distance"] as? String

            

                property.propertyType = propertyType
                property.price = price
                property.distance = distance


            

            properties.addObject(property)

        

        dispatch_async(dispatch_get_main_queue(),  () -> Void in

            self.delegate.itemsDownloaded(properties)

        )
    

这是我用来从数据库下载数据的代码:

import Foundation

class PropertyModel: NSObject 

    //properties

    var propertyType: String?
    var price: String?
    var distance: String?


    //empty constructor

    override init()
    

    

    //construct with @propertyType, @price and @distance parameters

    init(propertyType: String, price: String, distance: String) 

        self.propertyType = propertyType
        self.price = price
        self.distance = distance

    


    //prints object's current state

    override var description: String 
        return "Property Type: \(propertyType), Price: \(price), Distance: \(distance)"

    



最后,这是我用来尝试将其快速放入表格单元格的代码:

import UIKit

class First_ResultsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,    ListingModelProtocol  

    //Properties

    var feedItems: NSArray = NSArray()
    var selectedProperties : PropertyModel = PropertyModel()
    @IBOutlet weak var PropertyListTableView: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()
        //set delegates and initialize homeModel

        self.PropertyListTableView.delegate = self
        self.PropertyListTableView.dataSource = self

        let listingModel = ListingModel()
        listingModel.delegate = self
        listingModel.downloadItems()

        // Do any additional setup after loading the view.
    


    func itemsDownloaded(items: NSArray) 

        feedItems = items
        self.PropertyListTableView.reloadData()
    

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        // Return the number of feed items
        return feedItems.count

    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        // Retrieve cell
        let cellIdentifier: String = "BasicCell"
        let myCell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)!
        // Get the location to be shown
        let item: PropertyModel = feedItems[indexPath.row] as! PropertyModel
        // Get references to labels of cell
        myCell.textLabel!.text = item.propertyType

        return myCell
    


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    
    */



【问题讨论】:

你看过这里吗? ***.com/a/28129484/1585677 请将您的代码发布为文本,而不是图片。 【参考方案1】:

您发布的以下代码和您的评论不正确。

//the following insures none of the JsonElement values are nil through optional binding
if let propertyType = jsonElement["Property Type"] as? String,
    let price = jsonElement["Price"] as? String,
    let distance = jsonElement["Distance"] as? String

以上内容并不能确保这些值不是nil。您的 if 语句正在检查如果所有此 jsonElement 不是 nil 则它将进入并设置您的属性。

另外,如果上述任何一个属性在你的 json 响应中不是一个字符串,它就不会进入if 语句。您应该使用返回的类型对其进行检查。将 as? Double 替换为您的 json 响应返回的类型。

if let propertyType = jsonElement["Property Type"] as? String,
    let price = jsonElement["Price"] as? Double,
    let distance = jsonElement["Distance"] as? Double 

    property.propertyType = propertyType
    property.price = "\(price)"
    property.distance = "\(distance)"
 

如果您想在nil 时将其设置为空字符串,您应该使用as String ?? ""

//the following ensure that when the element is nil, we change it to a empty string and update our attributes
 let propertyType = jsonElement["Property Type"] as? String ?? ""
 let price = jsonElement["Price"] as? String ?? ""
 let distance = jsonElement["Distance"] as? String? ??

property.propertyType = propertyType
property.price = price
property.distance = distance

您不再需要 if 语句,因为它不会是 nil。

【讨论】:

但是问题是数据库中有值所以没有一个变量应该是零?我只想将数据库中的值添加到这些变量中并在表格单元格中显示它们 让你调试并查看 jsonElements 看看是否所有变量都像你的数据库一样存在? 再看一遍,可能是因为pricedistance的json响应不是字符串。因此它不存在。我现在将更新我的答案。让我知道您的数据库中的pricedistance 是什么? @AdamKona 我对表中的所有数据(VARCHAR)都使用了相同的数据类型,所以我不太清楚为什么这不起作用【参考方案2】:

如果这些 json 值不是 nil 且类型正确,则您正在使用可选绑定条件 (if let) 来检索它们。

但是,如果不是这种情况,并且其中一个或多个 json 键丢失或包含错误类型的值,会发生什么?看起来你的空PropertyModel 仍然被添加到你的properties 数组中,但是因为propertyTypepricedistance 从未设置过(听起来它们是可选的),它们将它们的默认值很可能为零。

您应该将properties.addObject(property) 行向上移动到if let 条件块内(直接在property.distance = distance 之下和 之上)。然后,您不会将任何具有 nil 值的 PropertyModel 添加到您的数组中。

【讨论】:

当我这样做时,它不再将属性放入表视图(这是最终目标),但实际上没有创建。我在上面添加了更多代码,以便可以正确查看所有代码 @AdamKona 如果这样做会导致没有 PoropertyModel 对象,那么要么您的 json 有错误(缺少您要查找的一个或多个键),要么您的代码正在尝试转换一个或多个当它们是 json 中的数字时,字符串的值,或者您的代码试图访问一个或多个键的错误名称。你能发布一个你正在解析的json的例子吗?

以上是关于我如何能够确保 json 元素不为零?的主要内容,如果未能解决你的问题,请参考以下文章

matlab找出两个向量都不为零的元素,并找出元素的位置

find函数

AVX:“如果不为零,则为 1”

Matlab - 各种函数学习

如果使用我的服务使用Java 8 lambda / streams列表不为空,如何从列表中删除每个元素

如何确保 cron 作业能够运行?