遍历自定义对象的属性

时间:2018-09-10 14:21:22

标签: json swift

我有一个具有以下结构的JSON响应:

GET

我已经为它创建了Swift父子结构:

父母:

{
    "id": {
        "sub_key1": "sub_value1",
        "sub_key2": "sub_value2",
        "sub_key3": "sub_value3",
        "used": false
    },
    "key1": {
        "sub_key1": "sub_value1",
        "sub_key2": "sub_value2",
        "sub_key3": "sub_value3",
        "used": true
    },
    "key2": {
        "sub_key1": "sub_value1",
        "sub_key2": "sub_value2",
        "sub_key3": "sub_value3",
        "used": false
    },
    "key3": {
        "sub_key1": "sub_value1",
        "sub_key2": "sub_value2",
        "sub_key3": "sub_value3",
        "used": true
    },
    "key4": {
        "sub_key1": "sub_value1",
        "sub_key2": "sub_value2",
        "sub_key3": "sub_value3",
        "used": false
    },
    "key5": {
        "sub_key1": "sub_value1",
        "sub_key2": "sub_value2",
        "sub_key3": "sub_value3",
        "used": true
    }
}

孩子:

struct Parent: Codable {
    let id: Child?
    let key1: Child?
    let key2: Child?
    let key3: Child?
    let key4: Child?
    let key5: Child?
}

现在,根据“已使用”的属性,仅使用了一些Child对象,我想过滤掉未使用的Child对象。我考虑过使用map方法,但这仅适用于数组。

关于如何解决该问题的任何想法?

2 个答案:

答案 0 :(得分:1)

我要像这样存储Parent

struct Parent {
    let children: [String: Child]
}

这将允许您使用parent.children.values.filter过滤子项,并为键添加一些动态性。

作为旁注:

Swift 4.2 将允许您进行动态通话。这意味着您可以实现:

extension Parent {
    subscript(dynamicMember member: String) -> Child? {
        get {
            return children[member]
        }
        set {
            children[member] = newValue
        }
    }
}

这将使您仍然可以调用parent.key1parent.id而不会失去可读性。

答案 1 :(得分:0)

首先将JSON数据转换为字典。然后,我获取该字典的值并从中创建一个数组。然后循环遍历该数组的每个字典,并将其转换为Child对象,然后将其保存在child数组(child对象的数组)中。

然后,我们将使用 filter 方法而不是map来过滤掉用作true的对象。

func fetchData() {

    let dataSourceURL = URL(string: "yourURL")!
    let request = URLRequest(url: dataSourceURL)
    UIApplication.shared.isNetworkActivityIndicatorVisible = true

    let task = URLSession(configuration: .default).dataTask(with: request) { data, response, error in

        let alertController = UIAlertController(title: "Oops!",
                                                message: "There was an error fetching json data.",
                                                preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default)
        alertController.addAction(okAction)

        if let data = data {
            do {
                let yourJSONAsDict =
                    try PropertyListSerialization.propertyList(from: data,
                                                               options: [],
                                                               format: nil) as! [String: Any]

                let valueArray = Array(yourJSONAsDict.values)
                var childArray = [Child]()
                for value in valueArray {
                    if let valueDict = value as? [String: Any] {
                        let childObj = Child(valueDict: valueDict)
                        childArray.append(childObj)
                    }
                }

                var filteredArray = childArray.filter{ ($0.used ?? false) }

                print(filteredArray)


            } catch {
                DispatchQueue.main.async {
                    self.present(alertController, animated: true, completion: nil)
                }
            }
        }

        if error != nil {
            DispatchQueue.main.async {
                UIApplication.shared.isNetworkActivityIndicatorVisible = false
                self.present(alertController, animated: true, completion: nil)
            }
        }
    }

    task.resume()
}

这是我正在使用的Child结构,供您参考

struct Child: Codable {
    let sub_key1: String?
    let sub_key2: String?
    let sub_key3: String?
    let used: Bool?

    init(valueDict: [String: Any]) {
        self.sub_key1 = valueDict["sub_key1"] as? String
        self.sub_key2 = valueDict["sub_key2"] as? String
        self.sub_key3 = valueDict["sub_key3"] as? String
        self.used = valueDict["used"] as? Bool
    }
}