我真的在努力把一个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。
我可能还会推荐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。”
这里还有一个答案??
好的。坚持住!之前所有的答案都是关于使用JSONSerialization,或返回nil,或忽略错误。
有什么不同
“我的解决方案”(不是真的我的解决方案,这是上述解决方案的混合)包含:
返回值的现代方法:Result<Value,Error>(返回值或错误)
避免使用空值
包含一个稍微详细的错误
使用扩展有漂亮/直观的界面:
提供了选择包的可能性
细节
Xcode 14
斯威夫特5.6.1
解决方案1。JSON文件->可解码
enum JSONParseError: Error {
case fileNotFound
case dataInitialisation(error: Error)
case decoding(error: Error)
}
extension Decodable {
static func from(localJSON filename: String,
bundle: Bundle = .main) -> Result<Self, JSONParseError> {
guard let url = bundle.url(forResource: filename, withExtension: "json") else {
return .failure(.fileNotFound)
}
let data: Data
do {
data = try Data(contentsOf: url)
} catch let error {
return .failure(.dataInitialisation(error: error))
}
do {
return .success(try JSONDecoder().decode(self, from: data))
} catch let error {
return .failure(.decoding(error: error))
}
}
}
方案一用途
struct Model: Decodable {
let uuid: String
let name: String
}
switch Model.from(localJSON: "myjsonfile") {
case .success(let value):
print(value)
case .failure(let error):
print(error)
}
解决方案2。JSON文件->字典
extension Dictionary where Key == String, Value == Any {
enum JSONParseError: Error {
case fileNotFound(filename: String)
case dataInitialisation(Error)
case jsonSerialization(Error)
case mappingFail(value: Any, toType: Any)
}
static func from(JSONfile url: URL) -> Result<Self, JSONParseError> {
let data: Data
do {
data = try Data(contentsOf: url)
} catch let error {
return .failure(.dataInitialisation(error))
}
let jsonObject: Any
do {
jsonObject = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
} catch let error {
return .failure(.jsonSerialization(error))
}
guard let jsonResult = jsonObject as? Self else {
return .failure(.mappingFail(value: jsonObject, toType: Self.Type.self))
}
return .success(jsonResult)
}
static func from(localJSONfile name: String) -> Result<Self, JSONParseError> {
let fileType = "json"
let fullFileName = name + (name.contains(fileType) ? "" : ".\(fileType)")
guard let path = Bundle.main.path(forResource: fullFileName, ofType: "") else {
return .failure(.fileNotFound(filename: fullFileName))
}
return from(JSONfile: URL(fileURLWithPath: path))
}
}
方案二使用
switch [String: Any].from(localJSONfile: "file.json") {
// OR switch [String: Any].from(localJSONfile: "file.json") {
// OR switch [String: Any].from(JSONfile: url) {
case let .success(dictionary):
print(dictionary)
case let .failure(error):
print("ERROR: \(error)")
}