加载字典数组的两个json文件。将缺少的字典从文件A添加到文件B

时间:2019-03-14 02:08:22

标签: arrays json swift dictionary

我需要同步两个json文件,以在应用程序更新后将新内容从文件A (位于应用程序捆绑包中)添加到文件B

两个json文件都是字典数组。我需要迭代文件A 的字典形式,并基于“ id”值,如果文件B 中没有字典,则需要添加那些缺少的字典,然后将文件B 保存回文件系统。

我有一个下面的解决方案可以做到这一点,并且似乎可行。但这太丑了!当然,我花了大约15分钟的时间将它们放在一起,但整个过程还是很安全的,但是我确信必须有更好的方法来解决这个问题。另外,我不想通过将这些字典转换为结构或模型以进行比较,而仅将它们转换回字典-> json来进一步混淆。

任何建议在这里都很棒!我更喜欢干净的代码,这是一团糟。

typealias JSON = [[String: Any]]
static private func uglySync() {
    let fileName: String = "someFileName"
    guard let sourceUrl = Bundle.main.url(forResource: fileName, withExtension: "json") else { return }
    guard let destinationDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
    let destinationUrl = destinationDirectory.appendingPathComponent("Data/" + fileName + ".json")

    do {
        let sourceData = try Data(contentsOf: sourceUrl)
        do {
            if let sourceArray = try JSONSerialization.jsonObject(with: sourceData, options: .mutableContainers) as? JSON {
                do {
                    let destinationData = try Data(contentsOf:  destinationUrl)
                    do {
                        if let destinationArray = try JSONSerialization.jsonObject(with: destinationData, options: .mutableContainers) as? JSON {
                            var mutableArray = destinationArray
                            sourceArray.forEach({ (item) in
                                if let itemId = item["id"] as? String {
                                    let foundItem = destinationArray.filter { $0["id"] as! String == itemId }.first
                                    if foundItem == nil {
                                        mutableArray.append(item)
                                    }
                                }
                            })

                            do {
                                let jsonData = try JSONSerialization.data(withJSONObject: mutableArray, options: .prettyPrinted)
                                try jsonData.write(to: destinationUrl)
                            } catch let error as NSError {
                                print("Couldn't write to file: \(error.localizedDescription)")
                            }
                        } else {
                            print("Cound not process json")
                        }
                    } catch {
                        print(error.localizedDescription)
                    }
                } catch {
                    print(error.localizedDescription)
                }
            } else {
                print("Cound not process json")
            }
        } catch {
            print(error.localizedDescription)
        }
    } catch {
        print(error.localizedDescription)
    }

    // oh wow the try catches :/
}

3 个答案:

答案 0 :(得分:1)

我将文件转换成jsonArray进行了分组,以简化do ... catch。另外,如果您不需要打印错误消息,则可以选择具有可选的try?来删除do ... catch块。

typealias JSONArray = [[String: Any]]

private func jsonArray(from fileURL: URL) -> JSONArray? {
    do {
        let fileData: Data = try Data(contentsOf: fileURL)
        guard let jsonArray = (try JSONSerialization.jsonObject(with: fileData, options: .mutableContainers)) as? JSONArray else {
            debugPrint("Failed to find JSON Array table")
            return nil
        }

        return jsonArray
    } catch {
        print(error.localizedDescription)
        return nil
    }
}

func sync() {
    let fileName: String = "someFileName"

    guard
        let fileURL: URL = Bundle.main.url(forResource: fileName, withExtension: "json"),
        let destinationDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first,
        let destinationURL: URL = destinationDirectory.appendingPathComponent("Data/" + fileName + ".json"),
        let sourceArray = jsonArray(from: fileURL),
        let destinationArray = jsonArray(from: destinationURL)
    else {
        return
    }

    var mutableArray = destinationArray
    let destinationIDArray = destinationArray.compactMap { $0["id"] as? String }

    mutableArray.forEach { (item) in
        if let itemId = item["id"] as? String, !(destinationIDArray.contains { $0 == itemId }) {
            mutableArray.append(item)
        }
    }

    // Update File
    do {
        let jsonData = try JSONSerialization.data(withJSONObject: mutableArray, options: .prettyPrinted)
        try jsonData.write(to: destinationURL)
    } catch {
        print("Couldn't write to file: \(error.localizedDescription)")
    }
}

答案 1 :(得分:0)

我认为您可以将不同的try放在同一do块中。

do {
  try function1()
  try function2()
} catch {
  print(error.localizedDescription)
}

所以之后您的功能可能看起来像

    typealias JSON = [[String: Any]]
    static private func moderatelyOkSync() {
        let fileName: String = "someFileName"
        guard let sourceUrl = Bundle.main.url(forResource: fileName, withExtension: "json") else { return }
        guard let destinationDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
        let destinationUrl = destinationDirectory.appendingPathComponent("Data/" + fileName + ".json")

        do {
            let sourceData = try Data(contentsOf: sourceUrl)
            if let sourceArray = try JSONSerialization.jsonObject(with: sourceData, options: .mutableContainers) as? JSON {
                let destinationData = try Data(contentsOf:  destinationUrl)
            }
            var mutableArray = destinationArray
            sourceArray.forEach({ (item) in
                if let itemId = item["id"] as? String {
                    let foundItem = destinationArray.filter { $0["id"] as! String == itemId }.first
                    if foundItem == nil {
                        mutableArray.append(item)
                    }
                }
            })
            let jsonData = try JSONSerialization.data(withJSONObject: mutableArray, options: .prettyPrinted)
            try jsonData.write(to: destinationUrl)

        } catch {
            print(error.localizedDescription)
        }

    }

答案 2 :(得分:0)

我要做的方法是用struct解码json文件,然后将其编码(序列化)到其他文件。因为执行该操作的代码将是2衬里,但您首先必须在结构中布置所有变量。可能仍然不是最佳