Цикл по свойствам пользовательского объекта - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть ответ JSON с такой структурой:

{
    "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
    }
}

Я создал Swift родительские и дочерние структуры для него следующим образом:

Родитель:

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

Ребенок:

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

Теперь используются только некоторые дочерние объекты, в зависимости от свойства used, и я хотел бы отфильтровать неиспользуемые дочерние объекты. Я думал об использовании метода map , но он работает только для массивов.

Есть идеи, как мне решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Я бы пошел с сохранением 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.key1 или parent.id и не потерять читабельность.

0 голосов
/ 10 сентября 2018

Сначала преобразуйте данные JSON в словарь. Затем я беру значения этого словаря и создаю из него массив. Затем переберите каждый словарь этого массива и преобразуйте его в дочерний объект и сохраните его в дочернем массиве (который является массивом дочерних объектов).

Тогда вместо карты мы будем использовать метод filter , чтобы отфильтровать объекты с использованием 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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...