使用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 }