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


当前回答

斯威夫特 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
    }

其他回答

这对我很有效

func readjson(fileName: String) -> NSData{

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

    return jsonData!
}

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 4 JSON类与可解码-为那些喜欢类

定义类如下:

class People: Decodable {
  var person: [Person]?

  init(fileName : String){
    // url, data and jsonData should not be nil
    guard let url = Bundle.main.url(forResource: fileName, withExtension: "json") else { return }
    guard let data = try? Data(contentsOf: url) else { return }
    guard let jsonData = try? JSONDecoder().decode(People.self, from: data) else { return }

    // assigns the value to [person]
    person = jsonData.person
  }
}

class Person : Decodable {
  var name: String
  var age: String
  var employed: String
}

用法,非常抽象:

let people = People(fileName: "people")
let personArray = people.person

这允许People类和Person类的方法,如果需要,变量(属性)和方法也可以标记为private。

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

使用这个泛型函数

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
}