我真的在努力把一个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。
简化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
注意,我们没有提供任何不必要的泛型,因此不需要强制转换parse的结果。
斯威夫特4。X和5。x使用可解码
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 readJSONFromFile<T: Decodable>(fileName: String, type: T.Type) -> T? {
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(T.self, from: data)
return jsonData
} catch {
print("error:\(error)")
}
}
return nil
}
下面这行代码:
let model = readJSONFromFile(fileName: "Model", type: Model.self)
对于这种类型:
struct Model: Codable {
let tall: Int
}
斯威夫特 5+
用Struct解码jsonData
if let jsonData = readFile(forName: <your file name>) {
do {
let decodedData = try JSONDecoder().decode(<your struct name>.self, from: jsonData)
return decodedData.<what you expect>
} catch { print("JSON decode error") }
}
这将读取文件并返回jsonData
如果你实际上在另一个bundle中(例如test),使用:
let bundlePath = Bundle(for: type(of: self))。路径(forResource: name, ofType: "json")
private func readFile(forName name: String) -> Data? {
do {
if let bundlePath = Bundle.main.path(forResource: name, ofType: "json"),
let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8) {
return jsonData
}
} catch {
print(error)
}
return nil
}
我可能还会推荐Ray Wenderlich的Swift JSON教程(它还涵盖了很棒的SwiftyJSON替代品,Gloss)。一段摘录(它本身并不能完全回答海报上的问题,但这个答案的附加价值是链接,所以请不要给它加-1):
在Objective-C中,解析和反序列化JSON相当简单:
NSArray *json = [NSJSONSerialization JSONObjectWithData:JSONData
options:kNilOptions error:nil];
NSString *age = json[0][@"person"][@"age"];
NSLog(@"Dani's age is %@", age);
在Swift中,由于Swift的可选选项和类型安全,解析和反序列化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中用空格/制表符缩进为我反序列化这个JSON。”