我真的很想尝试将一个JSON文件读入Swift,所以我可以玩它.我已经花了2天的时间重新搜索和尝试不同的方法,但没有运气,所以我已经注册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.
如果有人在寻找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.1回答(基于Abhishek的):
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 {} }
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 4使用Decodable
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 }
斯威夫特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 }
这对我有用
func readjson(fileName: String) -> NSData{ let path = NSBundle.mainBundle().pathForResource(fileName, ofType: "json") let jsonData = NSData(contentsOfMappedFile: path!) return jsonData! }
更新了Swift 3.0的名称
根据Abhishek的回答和Druva的回答
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 }
请遵循以下代码:
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 } } } }
数组"人员"将包含关键人物的所有数据.迭代通过获取它.
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 } }
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 }
copy-paste ready,第三方框架独立解决方案.
用法
let json:[[String : AnyObject]] = loadJSON(name: "Stations")!
这是我使用SwiftyJSON的解决方案
if let path : String = NSBundle.mainBundle().pathForResource("filename", ofType: "json") { if let data = NSData(contentsOfFile: path) { let json = JSON(data: data) } }
简化Peter Kreinz提供的示例。适用于Swift 4.2。
扩展功能:
extension Decodable { static func parse(jsonFile: String) -> Self? { guard let url = Bundle.main.url(forResource: jsonFile, withExtension: "json"), let data = try? Data(contentsOf: url), let output = try? JSONDecoder().decode(self, from: data) else { return nil } return output } }
示例模型:
struct Service: Decodable { let name: String }
用法示例:
/// service.json /// { "name": "Home & Garden" } guard let output = Service.parse(jsonFile: "service") else { // do something if parsing failed return } // use output if all good
该示例也适用于数组:
/// services.json /// [ { "name": "Home & Garden" } ] guard let output = [Service].parse(jsonFile: "services") else { // do something if parsing failed return } // use output if all good
注意,我们如何不提供任何不必要的泛型,因此我们不需要转换解析结果。
我提供了另一个答案,因为这里的所有答案都不适合从测试包中加载资源.如果您正在使用一个发出JSON的远程服务,并且想要在不触及实际服务的情况下对结果进行单元测试,则需要一个或多个响应并将它们放入项目的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,但获取测试包和加载文件的核心逻辑是问题的答案.