2017-02-17 42 views
1

我想从包中的myFile.json读取JSON文件,修改一些元素并将其作为JSON文件存储在文档目录中。我认为这将是一个简单的方法来坚持数据。随后,我打算读写文件目录。下面的代码显示了我做了什么并且受到了很多评论。看来我错过了一些重要步骤,因为预期的JSON转换不符合JSON规范。我很乐意提供关于如何在操场上进行测试的建议。该代码是基于从JSON获取意想不到的转换字典,并返回到JSON

Convert Dictionary to JSON in Swift

import UIKit 

/* Trying to read a json file from myFile.json in Bundle, modify some elemnts and store it 
in the document directory as a json file. Subsequently, intent to read and write to document directory 

myFile.json consistes of 

{ 
"record": {"id": "A1234", "customer": "Customer-1"} 
} 

*/ 


typealias MyRecord = [String: AnyObject] 
var json:MyRecord! 
let fileName = "myFile" 
var dictionary = MyRecord() 

func loadJsonFromBundle (forFilename fileName: String) -> MyRecord { 

    if let url = Bundle.main.url(forResource: fileName, withExtension: "json") { 
     if let data = NSData(contentsOf: url) { 
      do { 
       let dictionary = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as? [String:Any] 
       print("dictionary = \(dictionary!)") 
       /* displays 
       dictionary = ["record": { 
       customer = "Customer-1"; 
       id = A1234; 
       }] 
       */ 

       return dictionary! as MyRecord 
      } catch { 
       print("Error!! Unable to parse \(fileName).json") 
      } 
     } 
     print("Error!! Unable to load \(fileName).json") 
    } 

    return [:] 
} 

func loadJsonFromDocument (forFilename fileName: String) -> MyRecord { 

    let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) 
    if let url = docDirectory?.appendingPathComponent(fileName).appendingPathExtension("json") { 
     if let data = NSData(contentsOf: url) { 
      do { 
       let dictionary = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as? [String:Any] 
       print("dictionary = \(dictionary!)") 
       return dictionary! as MyRecord 
      } catch { 
       print("Error!! Unable to parse \(fileName).json") 
      } 
     } 
     print("Error!! Unable to load \(fileName).json") 
    } 

    return [:] 
} 


func saveJsonToFile (_ fileName:String, outString: String) -> URL { 
    let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) 
    if let fileURL = docDirectory?.appendingPathComponent(fileName).appendingPathExtension("json") { 
     print("fileURL = \(fileURL)") 
     // Write to a file on disk 

     do { 
      try outString.write(to: fileURL, atomically: true, encoding: .utf8) 
     } catch { 
      print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription) 
     } 
     return fileURL 
    } 
    return URL(string: "")! 
} 

let sq = "\"" 
func q(_ x:String) -> String { 
    return "\(sq)\(x)\(sq)" 
} 


dictionary = loadJsonFromBundle (forFilename: fileName) 
var a = dictionary["record"] as? [String:String] 
a?["customer"] = "newName" 
var dict = MyRecord() 
dict["record"] = a as AnyObject? 
print(dict) 

/* prints: 

["record": { 
customer = newName; 
id = A1234; 
}] 

*/ 

// https://stackoverflow.com/questions/29625133/convert-dictionary-to-json-in-swift/29628000#29628000 
do { 
    let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) 
    // here "jsonData" is the dictionary encoded in JSON data 

    let decoded = try JSONSerialization.jsonObject(with: jsonData, options: []) 
    // here "decoded" is of type `Any`, decoded from JSON data 

    // you can now cast it with the right type 
    if let dictFromJSON = decoded as? [String:Any] { 

     // need to save dictFromJson to a file in document directory 
     // saveJsonToFile is expecting a String for the json argument 
     // I converted dictFromJson to a string so I can save it 
     var outString = String(describing: dictFromJSON) 

     print("outString = \(outString)") 

     /* Notice that the internal structure is not quoted and there are semi-colons 

     outString = ["record": { 
     customer = newName; 
     id = A1234; 
     }] 

     */ 
     outString = outString.replacingOccurrences(of: "[", with: "{") 
     outString = outString.replacingOccurrences(of: "]", with: "}") 



     let url = saveJsonToFile("newFile", outString: String(describing: outString)) 
     print(url) 
     /* Resulting File looks like this: 

     {"record": { 
     customer = newName; 
     id = A1234; 
     }} 

     Question: Why were the braces swapped with brackets. The internal elements 
     were not quoted. 

     */ 

     // Will try to read back the json string from document directory 
     dictionary = loadJsonFromDocument(forFilename: fileName) 
     // results in ERROR (Unable to load myFile.json 


     a = dictionary["record"] as? [String:String] 
     a?["customer"] = "newName" 
     dict = MyRecord() 
     dict["record"] = a as AnyObject? 
     print(dict) 

    } 
} catch { 
    print(error.localizedDescription) 
} 
+0

你应该试试[String:Any]而不是[String:AnyObject]。 –

回答

1

问题是正确的,要存储在字典对象,而是变换到DataString然后写该String可以直接在DocumentDirectoryData

所以我改变了你的saveJsonToFile函数,它接受Data作为第二个参数而不是String

func saveJsonToFile (_ fileName:String, jsonData: Data) -> URL { 
    let docDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) 
    if let fileURL = docDirectory?.appendingPathComponent(fileName).appendingPathExtension("json") { 
     print("fileURL = \(fileURL)") 
     // Write to a file on disk 

     do { 
      try jsonData.write(to: fileURL) 
     } catch { 
      print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription) 
     } 
     return fileURL 
    } 
    return URL(string: "")! 
} 

现在只需在更改json结果并将其转换为数据后调用此函数。

do { 
    let jsonData = try JSONSerialization.data(withJSONObject: dict, options: []) 
    let url = saveJsonToFile("newFile", jsonData: jsonData) 
    print(url) 
} catch { 
    print(error.localizedDescription) 
} 
1

的问题是,您保存Dictionary对象文件,而不是编码的JSON。

仅使用从对象到数据的JSONSerialization,并且不通过.prettyprinted。通过vadian指出

do { 
    let jsonData = try JSONSerialization.data(withJSONObject: dict, options:[]) 
    // here "jsonData" is the dictionary encoded in JSON data 

    let outString = String(data:jsonData, encoding:.utf8) 

    print("outString = \(outString)") 
    let url = saveJsonToFile("newFile", outString: outString) 
    print(url) 
    } 
} catch { 
    print(error.localizedDescription) 
} 
+0

Vadian - 感谢您的快速反应和知识。答案应该是清楚的,但它没有登记。 –