【问题标题】:How to save/retrieve dictionary from file using SwiftyJSON如何使用 SwiftyJSON 从文件中保存/检索字典
【发布时间】:2017-04-29 22:09:35
【问题描述】:

我正在尝试从 Objc 转换为 swift 并且过得更好。

我有一堂带字典的课:

 collaborationDictionary:[String:Set<String>]

我正在尝试在文件中写入/读取此字典,但似乎无法使其正常工作。我必须使用以下 JSON 结构保存字典,并且必须使用 SwiftyJSON。

 { "Collaborations" : {
          "5604" : [
              "whiteboard.png",
              "VID_20161123_135117.3gp",
              "Photo_0.jpeg"]
          "5603" : [
              "VID_20161123_135117.3gp"],
          "5537" : [
              "Screenshot_20151212-132454.png",
              "VID_20161202_083205.3gp",
              "VID_20161123_135117.3gp",
              "Photo_0.jpeg",
              "Screenshot_20151212-132428.png",
              "Screenshot_20151212-132520.png",
              "IMG_20161017_132105.jpg",
              "whiteboard.png"]}
 }

我在查找/检索文件或写入文件方面没有任何实际问题。我只是不太清楚如何手动加载 SwiftyJSON。我需要在顶部有一个名为“Collaborations”的 JSON 对象。它需要包含一个协作 ID 字典(5604、5603...)。每个协作都包含一个字符串数组(文件名)。我包含了我用来读/写文件的代码,但我需要 SwiftyJSON 库的帮助。

这是我用来存储上述数据的成员数据成员:

这些是我需要完成的功能:

     private var collaborationDictionary:[String:Set<String>] = [:]


  func getUploadedFileSet() {
    collaborationDictionary = [:]
    let documentsURL = URL(string: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
    let appURL = documentsURL?.appendingPathComponent(APP_DISTINGUISHED_NAME)
    let jsonFileURL = appURL?.appendingPathComponent(UPLOADED_ITEMS_DB_JSON)

    if FileManager.default.fileExists(atPath: (jsonFileURL?.absoluteString)!) {
        do {
            let data = try Data(contentsOf: jsonFileURL!, options: .alwaysMapped)
            let json = JSON(data: data)

            // ************************************************
            // NEED HELP START
            // NOW WHAT????  What is the SwiftyJSON code

            ?????????????????????????                

            // NEED HELP END
            // ************************************************

        } catch let error {
            print(error.localizedDescription)
        }
    }
 }

  func saveUploadedFilesSet() {        
    let documentsURL = URL(string: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
    let appURL = documentsURL?.appendingPathComponent(APP_DISTINGUISHED_NAME)
    let jsonFileURL = appURL?.appendingPathComponent(UPLOADED_ITEMS_DB_JSON)

    do {
        let dirExists = FileManager.default.fileExists(atPath: (appURL?.absoluteString)!)
        if !dirExists {
            try FileManager.default.createDirectory(atPath: (appURL?.absoluteString)!, withIntermediateDirectories: false, attributes: nil)
        }

        // ************************************************
        // NEED HELP START
            // NOW WHAT????  What is the SwiftyJSON code

            ?????????????????????????                

        // NEED HELP END
        // ************************************************

        // Write to file code - haven't written it yet but that should be easy          

    } catch let error as NSError {
        print(error.localizedDescription);
    }
 }

任何方向将不胜感激。谢谢!

编辑

我能够弄清楚如何从文件中加载提供的 JSON 结构。这是代码:

 func getUploadedFileSet() {
    let documentsURL = URL(string: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
    let appURL = documentsURL?.appendingPathComponent(APP_DISTINGUISHED_NAME)
    let jsonFileURL = appURL?.appendingPathComponent(UPLOADED_ITEMS_DB_JSON)

    if FileManager.default.fileExists(atPath: (jsonFileURL?.absoluteString)!) {
        do {
            let data = try Data(contentsOf: jsonFileURL!, options: .alwaysMapped)
            let json = JSON(data: data)
            if json != nil {
                for (key, subJson) in json[kCollaborations] {
                    let stringArray:[String] = subJson.arrayValue.map { $0.string! }
                    let stringSet = Set(stringArray)
                    collaborationDictionary.updateValue(stringSet, forKey: key)
                }
            } else {
                print("Could not get json from file, make sure that file contains valid json.")
            }
        } catch let error {
            print(error.localizedDescription)
        }
    }

我还没有弄清楚如何将collaborationDictionary 对象保存到文件中。我最大的问题是弄清楚如何输入“协作”键。有什么想法吗?

【问题讨论】:

  • 您的具体问题是什么?
  • 具体来说,读写json对象的代码是什么。我将突出显示需要验证/修复或创建代码的部分。
  • 长话短说,您需要从磁盘加载文件吗?把它读成字符串?并使用 SwiftyJSON 序列化为 json?
  • 我明白这一点。我不知道该怎么做是专门使用“SwiftyJSON”。我正在更新上面的代码,以便您可以编写 ACTUAL swiftyJSON 来读取和写入 JSON 字符串。
  • 不是答案,但我强烈建议您在学习一门新语言时不要使用第三方库。

标签: ios swift swifty-json


【解决方案1】:

我终于让它工作了。最大的问题是我无法将协作字典转换为 JSON。我终于不得不将它转换为数组字典与集合字典。以下是两种方法:

     // **************************************************************************
func getUploadedFileSet() {
    let documentsURL = URL(string: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
    let appURL = documentsURL?.appendingPathComponent(APP_DISTINGUISHED_NAME)
    let jsonFileURL = appURL?.appendingPathComponent(UPLOADED_ITEMS_DB_JSON)

    if FileManager.default.fileExists(atPath: (jsonFileURL?.absoluteString)!) {
        do {
            let data = try Data(contentsOf: jsonFileURL!, options: .alwaysMapped)
            let json = JSON(data: data)
            if json != nil {
                for (key, subJson) in json[kCollaborations] {
                    let stringArray:[String] = subJson.arrayValue.map { $0.string! }
                    let stringSet = Set(stringArray)
                    collaborationDictionary.updateValue(stringSet, forKey: key)
                }
            } else {
                print("Could not get json from file, make sure that file contains valid json.")
            }
        } catch let error {
            print(error.localizedDescription)
        }
    }
}

// **************************************************************************
func saveUploadedFilesSet() {
    let documentsURL = URL(string: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
    let appURL = documentsURL?.appendingPathComponent(APP_DISTINGUISHED_NAME)
    let jsonFileURL = appURL?.appendingPathComponent(UPLOADED_ITEMS_DB_JSON)
    let adjustedJSONFileURL = URL(fileURLWithPath:(jsonFileURL?.absoluteString)!)

    do {
        let dirExists = FileManager.default.fileExists(atPath: (appURL?.absoluteString)!)
        if !dirExists {
            try FileManager.default.createDirectory(atPath: (appURL?.absoluteString)!, withIntermediateDirectories: false, attributes: nil)
        }

        // Convert set elements to arrays
        var convertedCollaborationDictionary: [String:[String]] = [:]
        for (sessionID, fileNameSet) in collaborationDictionary {
            let array = Array(fileNameSet)
            convertedCollaborationDictionary.updateValue(array, forKey: sessionID)
        }
        let json: JSON = JSON(convertedCollaborationDictionary)
        let fullJSON: JSON = [kCollaborations:json.object]
        let data = try fullJSON.rawData()
        try data.write(to: adjustedJSONFileURL, options: .atomic)

    } catch let error as NSError {
        print(error.localizedDescription);
    }
}

【讨论】:

    【解决方案2】:

    如果你深入研究源码,SwiftyJSON 包装了 JSONSerialization,它既可以被初始化又可以转换回知道如何从磁盘读取和写入自身的 Data:

      func readJSON() -> JSON? {
          guard let url = Bundle.main.url(forResource: "data", withExtension: "json"),
                let data = try? Data(contentsOf: url) else {
              return nil
          }
          return JSON(data: data)
      }
    
      func write(json: JSON, to url: URL) throws {
          let data = try json.rawData()
          try data.write(to: url)
      }
    

    请注意,您可以从任何地方(包括 Bundle)加载静态数据,但您只能写入沙箱(即 Documents 目录)。如果您计划读取/写入同一个文件,您可能希望在首次运行时从 Bundle 复制到文档目录。

    您的示例 JSON 也很糟糕(lint it)。 “Photo_0.jpeg”后面需要一个逗号]

    【讨论】:

    • 我了解如何将 JSON 转换为数据对象并返回。如何加载问题中指定的协作字典对象?如何将协作字典转换回 SwiftyJSON。 JSON 是正确的。数组元素后跟逗号,除非它们是数组中的最后一个元素。
    • 您是否运行了我发布的代码?如果您将 json 复制到 data.json 文本文件中并将该文件放入您的项目中并调用 readJSON() 函数它会失败(print(readJSON) 显示 nil),但是如果您添加逗号它可以工作并且您会得到完整的控制台中的 JSON 对象。
    • 问题是它没有回答问题:问题是如何转换以下成员数据:collaborationDictionary:[String:Set] from SwiftyJSON (SJ) 并将其转换回来到 SJ。从我的代码中可以看出,我已经将文件加载到数据对象中。我只是不知道如何将 SwiftyJSON 数据放入 var CollaborationDictionary:[String:Set] 中。另外,我没有将编写它的实际代码放入文件中,但这也很简单。我只是不知道如何将协作字典放入 SwiftyJSON。通过 SwiftyJSON,我的意思是一个 JSON 对象。
    • SwiftyJSON 不会序列化和反序列化类/结构。如果这是您想要的,您应该使用 ObjectMapper 将 [String : Any] 转换为可用于初始化 JSON 的 [String : Any] 。 github.com/Hearst-DD/ObjectMapper
    猜你喜欢
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    • 2016-12-18
    • 1970-01-01
    • 2019-10-22
    • 2015-11-23
    • 2013-10-12
    相关资源
    最近更新 更多