我真的在努力把一个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。


当前回答

//change type based on your struct and right JSON file

let quoteData: [DataType] =
    load("file.json")

func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
    let data: Data

    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}


其他回答

下面的代码适用于我。我用的是Swift 5

let path = Bundle.main.path(forResource: "yourJSONfileName", ofType: "json")
var jsonData = try! String(contentsOfFile: path!).data(using: .utf8)!

然后,如果你的Person结构(或类)是可解码的(以及它的所有属性),你可以简单地做:

let person = try! JSONDecoder().decode(Person.self, from: jsonData)

我避免了所有的错误处理代码,使代码更容易读懂。

我可能还会推荐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。”

这对我很有效

func readjson(fileName: String) -> NSData{

    let path = NSBundle.mainBundle().pathForResource(fileName, ofType: "json")
    let jsonData = NSData(contentsOfMappedFile: path!)

    return jsonData!
}
//change type based on your struct and right JSON file

let quoteData: [DataType] =
    load("file.json")

func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
    let data: Data

    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}


Swift 5的答案为我工作,除了我必须添加一个空文件,重命名为xxx。Json,并使用泛型。

func loadJson<T:Codable>(filename fileName: String) -> T? {
        if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
            do {
                let data = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                return  try decoder.decode(T.self, from: data)
            } catch {
                print("error:\(error)")
            }
        }
        return nil
    }

code