Swift - 使用 swiftyJSON 根据字典中的值查找字典数组的索引

Posted

技术标签:

【中文标题】Swift - 使用 swiftyJSON 根据字典中的值查找字典数组的索引【英文标题】:Swift - Find the index of an array of dictionaries based on the value in the dictionaries using swiftyJSON 【发布时间】:2015-03-24 10:17:17 【问题描述】:

我对编程很陌生,更不用说 Swift 了。我从以前的编程尝试中了解了一些概念,因此我比以往任何时候都走得更远。如果我不清楚我需要什么,我深表歉意。

我正在提取警报列表的 JSON 数据,并尝试使用 swiftyJSON 解析数据,我认为这可以解决问题,但我遇到了尝试从数组中的某些字典中获取一些数据的障碍, 不幸的是,在这个数组中的字典里面是电子邮件地址的位置,不同的字典在彼此之间使用相似的键。

我将向您展示我的结构、函数和 JSON 数据。请帮我获取电子邮件地址、服务 - 它的 ID 和标签。此外,显示的数据中可能存在不止一项服务,我需要捕获所有服务。

这是 JSON 数据:


"hasNext": false,
"data": [
    
        "status": [
            1,
            "READ"
        ],
        "resolutionStatus": [
            0,
            "OPEN"
        ],
        "description": "There is some description here",
        "title": "Some Activity",
        "entities": [
            
                "view_name": "audits",
                "type": "link",
                "parameters": 
                    "orgUnit": "/"
                ,
                "label": "/"
            ,
            
                "type": "user",
                "id": "hidden@hidden.com",
                "label": "hidden@hidden.com"
            ,
            
                "type": "service",
                "id": 6666,
                "label": "someService"
            ,
            
                "type": "service",
                "id": 7777,
                "label": "anotherService"
            
        ],
        "stories": [
            5
        ],
        "date": "2014-12-10T23:46:28.067000Z",
        "audits": [
            "ljBhqKQVOF9w",
            "pISQyT9iy9w",
            "oynGf2_CIw"
        ],
        "_id": "54fdad0dfd",
        "id": [
            14683,
            "ALERT_SOME_ACTIVITY"
        ],
        "severity": [
            5,
            "HIGH"
        ]
    

这是我的结构:

    struct AlertModel: Printable 
    let alertUser: String?
    let alertService: String?
    let alertTitle: String?
    let alertReadStatus: String?
    let alertResolutionStatus: String?
    let alertDescription: String?
    let alertEntities: Array <String> = []
    let alertDate: String?
    let alertAudits: Array <String> = []
    let alertId: String?
    let

     alertSeverity: String?

      // change description to print to console
         var description: String 
            return "User: \(alertUser)\nService: \(alertService)\nTitle: \(alertTitle!)\nRead Status: \(alertReadStatus!)\nResolution Status: \(alertResolutionStatus!)\nDescription: \(alertDescription!)\nDate: \(alertDate!)\nAlert ID: \(alertId!)\nSeverity: \(alertSeverity!)\n******************************************\n"
        

        init(alertUser: String?, alertService: String?, alertTitle: String?, alertReadStat

us: String?, alertResolutionStatus: String?, alertDescription: String?/*, alertEntities: Array<String>*/, alertDate: String?/*, alertAudits: Array<String>*/, alertId: String?, alertSeverity: String?) 
        self.alertUser = alertUser
        self.alertService = alertService
        self.alertTitle = alertTitle
        self.alertReadStatus = alertReadStatus
        self.alertResolutionStatus = alertResolutionStatus
        self.alertDescription = alertDescription
        //self.alertEntities = alertEntities
        self.alertDate = alertDate
        //self.alertAudits = alertAudits
        self.alertId = alertId
        self.alertSeverity = alertSeverity
    

功能如下:

let jsonAlert = JSON(data: jsonAlertObject)
    if let alertArray = jsonAlert["data"].array 
        var alerts = [AlertModel]()
        for alertDict in alertArray 
            let alertTitle: String? = alertDict["title"].stringValue
            let alertReadStatus: String? = alertDict["status"][1].stringValue
            let alertResolutionStatus: String? = alertDict["resolutionStatus"][1].stringValue
            let alertDescription: String? = alertDict["description"].stringValue
            let alertDate: String? = alertDict["date"].stringValue
            let alertId: String? = alertDict["_id"].stringValue

            // Need to grab the type and label from each dictionary in the array of entities
            let alertEntitiesArray: Array? = alertDict["entities"].arrayObject
            var arrayIndex = 0
            var entitiesDict = ["" : ""]
            while arrayIndex < alertEntitiesArray?.count 
                entitiesDict[alertDict["entities"][arrayIndex]["type"].stringValue] = alertDict["entities"][arrayIndex]["label"].stringValue
                arrayIndex++
            
            let alertService: String? = entitiesDict["service"]
            let alertUser: String? = entitiesDict["user"]
            let alertSeverity: String? = alertDict["severity"][1].stringValue

            let alert = AlertModel(alertUser: alertUser, alertService: alertService, alertTitle: alertTitle, alertReadStatus: alertReadStatus, alertResolutionStatus: alertResolutionStatus, alertDescription: alertDescription, alertDate: alertDate, alertId: alertId, alertSeverity: alertSeverity)
            alerts.append(alert)
            var alertsDictionaryByID = [alertId!: alert]

        
        println(alerts)
    

如您所见,JSON 数据有几个层次。我可以毫无问题地获取数据并将其提取出来。问题是“实体”数组中可能并不总是包含相同的数据。我有多个服务,它可能没有电子邮件地址,对于数组的第一个值,它可能有一组完全不同的数据。

我正在尝试获取电子邮件地址。如果我能找到一种方法来像字典数据一样搜索“用户”,然后当找到它时,它将返回数组索引值以便能够直接引用它,因为我永远不会知道索引号是用户值的一部分.

我希望我的理解足够清楚,有人可以帮助我。 --- 我的下一步将使用每个单独的警报填充一个 listView。

【问题讨论】:

【参考方案1】:

我也在使用 SwiftyJSON,但使用 NSURLConnection 很简单。喜欢这种方法。

//MARK: - NSURLConnection Delegate methods


    var responseData : NSMutableData = NSMutableData()

    func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!)
    
        self.responseData.length = 0
    

    func connection(connection: NSURLConnection!, didReceiveData data: NSData!)
    
        self.responseData.appendData(data)
    


    func connectionDidFinishLoading(connection: NSURLConnection!)
    
        if let responseDatas = responseData as NSData? 

            if let jsonResult : NSDictionary = NSJSONSerialization.JSONObjectWithData(responseDatas, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary? 


                if let dataArray = jsonResult.valueForKeyPath("data") as? NSArray 
                 

                  if let entitiesArray = dataArray.valueForKeyPath("entities") as? NSArray 
                 

                 if let firstArray = dataArray[0] 
                 
                     // access your viewName and types here
                                     

                     // Like this method, convert all your parameters and access it.

                                    
                
                else
                
               // Do something here
                

            
            else
            
                 // Do something here

            
        
        else
        
             // Do something here

        



    

    func connection(connection: NSURLConnection!, didFailWithError error: NSError!)
    
     // Do something here
    

【讨论】:

感谢您的回复。我尝试添加它,但在最后一个 if-let 语句 '1.常量“firstEntitiesArray”推断为“AnyObject”类型,这可能是意外的。这个指向 firstArray。 '2。条件绑定中的绑定值必须是可选类型。这个指向dataArray [0]。'你能帮我理解最后一个if-let语句如何帮助我找到我正在寻找的键\值吗?如果没有 swiftyJSON,这似乎很简单,但正如我所说,我还是新手,所以我可能无法推断出你所期望的我所知道的东西。 你能帮我理解最后一个 if-let 语句如何帮助我找到我正在寻找的键\值吗?如果没有 swiftyJSON,这似乎很简单,但正如我所说,我还是新手,所以我可能无法推断出你所期望的我所知道的东西。【参考方案2】:

我最终发现 SwiftyJSON 和 Alamofire 可以极大地帮助网络和 JSON 序列化。

就数组中字典的问题而言,我最终创建了一个函数,该函数遍历实体数组,分别查看每个字典,然后根据 key="type" 执行 Switch 语句以确定它是否是“用户”字典或“服务”字典,然后将“类型”值(表示它是用户还是服务)与“标签”的值(用户名或服务名称)结合起来,并创建一个新的字典,然后我可以引用它来放回我的数据模型中。

class func retrieveDataFromEntitiesArray (alertDict: JSON) -> (entitesDict: Dictionary<String, String>, servicesArray: [String]) 
    // Need to create an array object, instead of a JSON object, of the entities array to be able to get a count to run the while against.
    var arrayIndex = 0
    var entitiesDict: Dictionary<String, String> = [:]
    var alertEntitiesArray = alertDict.arrayObject
    var servicesArray = [String]()
    while arrayIndex < alertEntitiesArray?.count 
        var dictKey = alertDict[arrayIndex]["type"].string
        switch (dictKey!) 
        case "user":
            entitiesDict[alertDict[arrayIndex]["type"].stringValue] = alertDict[arrayIndex]["label"].stringValue
        case "service":
            servicesArray.append(alertDict[arrayIndex]["label"].stringValue)
        case "policyRule":
            entitiesDict[alertDict[arrayIndex]["type"].stringValue] = alertDict[arrayIndex]["label"].stringValue
        default:
            println("Nothing Here")
        
        arrayIndex++
    
    return (entitiesDict, servicesArray)

【讨论】:

以上是关于Swift - 使用 swiftyJSON 根据字典中的值查找字典数组的索引的主要内容,如果未能解决你的问题,请参考以下文章

Swift 2 + SwiftyJSON:使用未解决的标识符错误

swift、Alamofire、SwiftyJSON:如何解析 arrayObject

“当前 SwiftyJSON(通过 Swift 3.0.2)无法使用 Swift 3.1 导入”的原因是啥

SwiftyJSON 问题 Swift 2

Swift - 使用 SwiftyJSON 从 JSON 中获取字符串数组

使用 SwiftyJSON 将 JSON 数组反序列化为 Swift 对象