使用Swift读取JSON文件

我真的努力尝试读取一个JSON文件到Swift中,所以我可以玩弄它。 我已经花了2天的最好的一部分重新search和尝试不同的方法,但没有运气,因此,我已经注册到StackOverFlow,看看有没有人可以指出我在正确的方向…..

我的JSON文件名为test.json,包含以下内容:

{ "person":[ { "name": "Bob", "age": "16", "employed": "No" }, { "name": "Vinny", "age": "56", "employed": "Yes" } ] } 

该文件直接存储在文档中,并使用以下代码访问它:

 let file = "test.json" let dirs : String[] = NSSearchPathForDirectoriesInDomains( NSSearchpathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainMask, true) as String[] if (dirs != nil) { let directories: String[] = dirs let dir = directories[0] let path = dir.stringByAppendingPathComponent(file) } var jsonData = NSData(contentsOfFile:path, options: nil, error: nil) println("jsonData \(jsonData)" // This prints what looks to be JSON encoded data. var jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as? NSDictionary println("jsonDict \(jsonDict)") - This prints nil..... 

如果任何人都可以给我一个正确的方向,我可以如何反序列化JSON文件,并把它放在一个可访问的Swift对象,我将永远感激!

亲切的问候,

Krivvenz。

按照下面的代码:

 if let path = NSBundle.mainBundle().pathForResource("test", ofType: "json") { if let jsonData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil) { if let jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary { if let persons : NSArray = jsonResult["person"] as? NSArray { // Do stuff } } } } 

数组“人员”将包含关键人物的所有数据。 迭代通过获取它。

Swift 4.0

 if let path = Bundle.main.path(forResource: "test", ofType: "json") { do { let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) if let jsonResult = jsonResult as? Dictionary<String, AnyObject>, let person = jsonResult["person"] as? [Any] { // do stuff } } catch { // handle error } } 

如果有人正在寻找SwiftyJSON答案:
更新:
对于Swift 3/4

 if let path = Bundle.main.path(forResource: "assets/test", ofType: "json") { do { let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped) let jsonObj = try JSON(data: data) print("jsonData:\(jsonObj)") } catch let error { print("parse error: \(error.localizedDescription)") } } else { print("Invalid filename/path.") } 

对于Swift 2

 if let path = NSBundle.mainBundle().pathForResource("assets/test", ofType: "json") { do { let data = try NSData(contentsOfURL: NSURL(fileURLWithPath: path), options: NSDataReadingOptions.DataReadingMappedIfSafe) let jsonObj = JSON(data: data) if jsonObj != JSON.null { print("jsonData:\(jsonObj)") } else { print("could not get json from file, make sure that file contains valid json.") } } catch let error as NSError { print(error.localizedDescription) } } else { print("Invalid filename/path.") } 

Xcode 8 Swift 3从文件更新中读取json:

  if let path = Bundle.main.path(forResource: "userDatabseFakeData", ofType: "json") { do { let jsonData = try NSData(contentsOfFile: path, options: NSData.ReadingOptions.mappedIfSafe) do { let jsonResult: NSDictionary = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary if let people : [NSDictionary] = jsonResult["person"] as? [NSDictionary] { for person: NSDictionary in people { for (name,value) in person { print("\(name) , \(value)") } } } } catch {} } catch {} } 

更新Swift 3.0的名称

根据阿布舍克的回答和德鲁娃的回答

 func loadJson(forFilename fileName: String) -> NSDictionary? { 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? NSDictionary return dictionary } catch { print("Error!! Unable to parse \(fileName).json") } } print("Error!! Unable to load \(fileName).json") } return nil } 

Swift 2.1回答(基于阿布舍克的):

  if let path = NSBundle.mainBundle().pathForResource("test", ofType: "json") { do { let jsonData = try NSData(contentsOfFile: path, options: NSDataReadingOptions.DataReadingMappedIfSafe) do { let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary if let people : [NSDictionary] = jsonResult["person"] as? [NSDictionary] { for person: NSDictionary in people { for (name,value) in person { print("\(name) , \(value)") } } } } catch {} } catch {} } 

Swift 3.0,Xcode 8,iOS 10

  if let path = Bundle.main.url(forResource: "person", withExtension: "json") { do { let jsonData = try Data(contentsOf: path, options: .mappedIfSafe) do { if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? NSDictionary { if let personArray = jsonResult.value(forKey: "person") as? NSArray { for (_, element) in personArray.enumerated() { if let element = element as? NSDictionary { let name = element.value(forKey: "name") as! String let age = element.value(forKey: "age") as! String let employed = element.value(forKey: "employed") as! String print("Name: \(name), age: \(age), employed: \(employed)") } } } } } catch let error as NSError { print("Error: \(error)") } } catch let error as NSError { print("Error: \(error)") } } 

输出:

 Name: Bob, age: 16, employed: No Name: Vinny, age: 56, employed: Yes 
 fileprivate class BundleTargetingClass {} func loadJSON<T>(name: String) -> T? { guard let filePath = Bundle(for: BundleTargetingClass.self).url(forResource: name, withExtension: "json") else { return nil } guard let jsonData = try? Data(contentsOf: filePath, options: .mappedIfSafe) else { return nil } guard let json = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) else { return nil } return json as? T } 

👆🏻复制粘贴,第三方框架独立解决scheme。

用法👇🏻

let json:[[String : AnyObject]] = loadJSON(name: "Stations")!

这对我很好

 func readjson(fileName: String) -> NSData{ let path = NSBundle.mainBundle().pathForResource(fileName, ofType: "json") let jsonData = NSData(contentsOfMappedFile: path!) return jsonData! } 

这是我使用SwiftyJSON的解决scheme

 if let path : String = NSBundle.mainBundle().pathForResource("filename", ofType: "json") { if let data = NSData(contentsOfFile: path) { let json = JSON(data: data) } } 

Swift 4使用可解码

 struct ResponseData: Decodable { var person: [Person] } struct Person : Decodable { var name: String var age: String var employed: String } func loadJson(filename fileName: String) -> [Person]? { if let url = Bundle.main.url(forResource: fileName, withExtension: "json") { do { let data = try Data(contentsOf: url) let decoder = JSONDecoder() let jsonData = try decoder.decode(ResponseData.self, from: data) return jsonData.person } catch { print("error:\(error)") } } return nil } 

Swift 3

 func loadJson(filename fileName: String) -> [String: AnyObject]? { if let url = Bundle.main.url(forResource: fileName, withExtension: "json") { do { let data = try Data(contentsOf: url) let object = try JSONSerialization.jsonObject(with: data, options: .allowFragments) if let dictionary = object as? [String: AnyObject] { return dictionary } } catch { print("Error!! Unable to parse \(fileName).json") } } return nil } 

我提供了另一个答案,因为这里没有一个适合从testing包加载资源。 如果您正在使用放出JSON的远程服务,并希望unit testingparsing结果而不碰到实际的服务,那么您将采取一个或多个响应,并将它们放到项目的Tests文件夹中的文件中。

 func testCanReadTestJSONFile() { let path = NSBundle(forClass: ForecastIOAdapterTests.self).pathForResource("ForecastIOSample", ofType: "json") if let jsonData = NSData(contentsOfFile:path!) { let json = JSON(data: jsonData) if let currentTemperature = json["currently"]["temperature"].double { println("json: \(json)") XCTAssertGreaterThan(currentTemperature, 0) } } } 

这也使用SwiftyJSON,但获取testing包和加载文件的核心逻辑是问题的答案。

最新的swift 3.0绝对有效

 func loadJson(filename fileName: String) -> [String: AnyObject]? { if let url = Bundle.main.url(forResource: fileName, withExtension: "json") { if let data = NSData(contentsOf: url) { do { let object = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) if let dictionary = object as? [String: AnyObject] { return dictionary } } catch { print("Error!! Unable to parse \(fileName).json") } } print("Error!! Unable to load \(fileName).json") } return nil } 

以最安全的方式更新了Swift 3

  private func readLocalJsonFile() { if let urlPath = Bundle.main.url(forResource: "test", withExtension: "json") { do { let jsonData = try Data(contentsOf: urlPath, options: .mappedIfSafe) if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? [String: AnyObject] { if let personArray = jsonDict["person"] as? [[String: AnyObject]] { for personDict in personArray { for (key, value) in personDict { print(key, value) } print("\n") } } } } catch let jsonError { print(jsonError) } } } 

在这里输入图像说明

基于阿布舍克的回答 ,对于iOS 8来说,这将是:

 let masterDataUrl: NSURL = NSBundle.mainBundle().URLForResource("masterdata", withExtension: "json")! let jsonData: NSData = NSData(contentsOfURL: masterDataUrl)! let jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as! NSDictionary var persons : NSArray = jsonResult["person"] as! NSArray 

这对XCode 8.3.3有效

 func fetchPersons(){ if let pathURL = Bundle.main.url(forResource: "Person", withExtension: "json"){ do { let jsonData = try Data(contentsOf: pathURL, options: .mappedIfSafe) let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as! [String: Any] if let persons = jsonResult["person"] as? [Any]{ print(persons) } }catch(let error){ print (error.localizedDescription) } } } 

我使用下面的代码从工程目录下的FAQ-data.json文件中获取JSON

我正在使用Swift在Xcode 7.3中实现。

  func fetchJSONContent() { if let path = NSBundle.mainBundle().pathForResource("FAQ-data", ofType: "json") { if let jsonData = NSData(contentsOfFile: path) { do { if let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary { if let responseParameter : NSDictionary = jsonResult["responseParameter"] as? NSDictionary { if let response : NSArray = responseParameter["FAQ"] as? NSArray { responseFAQ = response print("response FAQ : \(response)") } } } } catch { print("Error while parsing: \(error)") } } } } override func viewWillAppear(animated: Bool) { fetchFAQContent() } 

JSON文件的结构:

 { "status": "00", "msg": "FAQ List ", "responseParameter": { "FAQ": [ { "question": “Question No.1 here”, "answer": “Answer goes here”, "id": 1 }, { "question": “Question No.2 here”, "answer": “Answer goes here”, "id": 2 } . . . ] } } 

我也可能会推荐Ray Wenderlich的Swift JSON教程 (其中也包括令人敬畏的SwiftyJSON替代scheme, Gloss )。 一个摘录(本身授予,不完全回答海报,但这个答案的附加价值是链接,所以请不要-1)。

在Objective-C中,parsing和反序列化JSON相当简单:

 NSArray *json = [NSJSONSerialization JSONObjectWithData:JSONData options:kNilOptions error:nil]; NSString *age = json[0][@"person"][@"age"]; NSLog(@"Dani's age is %@", age); 

在Swift中,由于Swift选项和types安全,parsing和反序列化JSON有点繁琐[但是作为Swift 2.0的一部分,引入了guard语句来帮助摆脱嵌套if语句:

 var json: Array! do { json = try NSJSONSerialization.JSONObjectWithData(JSONData, options: NSJSONReadingOptions()) as? Array } catch { print(error) } guard let item = json[0] as? [String: AnyObject], let person = item["person"] as? [String: AnyObject], let age = person["age"] as? Int else { return; } print("Dani's age is \(age)") 

当然,在XCode 8.x中,只需双击空格键,然后说“嘿,Siri,请在Swift 3.0中使用空格/制表符对我进行反序列化。

SWIFTYJSON版本SWIFT 3

 func loadJson(fileName: String) -> JSON { var dataPath:JSON! if let path : String = Bundle.main.path(forResource: fileName, ofType: "json") { if let data = NSData(contentsOfFile: path) { dataPath = JSON(data: data as Data) } } return dataPath }