我需要同步两个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 :/
}
答案 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衬里,但您首先必须在结构中布置所有变量。可能仍然不是最佳