Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift、NSJ系列化和NSError_Swift_Nsjsonserialization_Nserror - Fatal编程技术网

Swift、NSJ系列化和NSError

Swift、NSJ系列化和NSError,swift,nsjsonserialization,nserror,Swift,Nsjsonserialization,Nserror,问题是当存在不完整的数据时,NSJSONSerialization.JSONObjectWithData会使应用程序崩溃,并在展开可选值时意外发现nil错误,而不是使用NSError变量通知我们。所以我们无法防止坠机 您可以在下面找到我们正在使用的代码 var error:NSError? = nil let dataToUse = NSJSONSerialization.JSONObjectWithData(receivedData, options: NSJSO

问题是当存在不完整的数据时,
NSJSONSerialization.JSONObjectWithData
会使应用程序崩溃,并在展开可选值时意外发现nil错误,而不是使用NSError变量通知我们。所以我们无法防止坠机

您可以在下面找到我们正在使用的代码

      var error:NSError? = nil

      let dataToUse = NSJSONSerialization.JSONObjectWithData(receivedData, options:   NSJSONReadingOptions.AllowFragments, error:&error) as NSDictionary

    if error != nil { println( "There was an error in NSJSONSerialization") }

到目前为止,我们还无法找到解决方法。

问题在于,您在之前强制转换了JSON反序列化的结果 检查错误。如果JSON数据无效(例如不完整),则

返回
nil

NSJSONSerialization.JSONObjectWithData(...) as NSDictionary
将会崩溃

以下是正确检查错误条件的版本:

var error:NSError? = nil
if let jsonObject: AnyObject = NSJSONSerialization.JSONObjectWithData(receivedData, options: nil, error:&error) {
    if let dict = jsonObject as? NSDictionary {
        println(dict)
    } else {
        println("not a dictionary")
    }
} else {
    println("Could not parse JSON: \(error!)")
}
备注:

  • 检查错误的正确方法是测试返回值,而不是 错误变量
  • JSON读取选项
    .AllowFragments
    在这里没有帮助。设置此选项 例如,仅允许非
    NSArray
    NSDictionary
    实例的顶级对象

    { "someString" }
    
您也可以在一行中完成,使用可选的强制转换
as?

if let dict = NSJSONSerialization.JSONObjectWithData(receivedData, options: nil, error:nil) as? NSDictionary {
    println(dict)
} else {
    println("Could not read JSON dictionary")
}
缺点是在
else
情况下,您无法区分是否正在阅读 JSON数据失败,或者JSON不代表字典

有关Swift 3的更新,请参阅。

已更新Swift 3

let jsonData = Data()
do {
    let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options:JSONSerialization.ReadingOptions(rawValue: 0))
    guard let dictionary = jsonObject as? Dictionary<String, Any> else {
        print("Not a Dictionary")
        // put in function
        return
    }
    print("JSON Dictionary! \(dictionary)")
}
catch let error as NSError {
    print("Found an error - \(error)")
}

以下是一个Swift 2扩展,可用于仅反序列化NSDictionary:

extension NSJSONSerialization{
    public class func dictionaryWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> NSDictionary{
        guard let d: NSDictionary = try self.JSONObjectWithData(data, options:opt) as? NSDictionary else{
            throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotParseResponse, userInfo: [NSLocalizedDescriptionKey : "not a dictionary"])
        }
        return d;
    }
}

抱歉,我不确定如何执行保护返回以避免创建临时“d”。

Swift 3 NSJSONSerialization示例(从文件中读取json):

文件data.json(此处示例:)

文件JSONSerialization.swift

用法 结果(日志屏幕截图)
Swift 3:

let jsonData = Data()
do {
    guard let parsedResult = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? NSDictionary else {
        return
    }
    print("Parsed Result: \(parsedResult)")
} catch {
    print("Error: \(error.localizedDescription)")
}

您解释为“这是一个正确检查错误条件的版本”的部分也没有捕获错误。它在以下行被压碎:AnyObject=NSJSONSerialization.JSONObjectWithData(receivedData,options:NSJSONReadingOptions.AllowFragments,error:&error)!我想说的是,如果收到的数据没有问题,我提交的这段代码和以前的代码都可以正常工作。@Hope:这不是我的建议。如果您使用
强制打开结果
那么您与NSDictionary的强制强制转换
有相同的问题:如果结果为零,它将崩溃。让dataToUse:AnyObject?=NSJSONSerialization.JSONObjectWithData(receivedData,选项:NSJSONReadingOptions.AllowFragments,error:&error)似乎没有问题。所以我正在核对你们回答的问题。至少你对这个主题的理解更好。哎哟,和objc相比,swift的语法真的很糟糕。“let”、“do”、“try”、“guard”、“as?”、“catch”…这么多行话。如果你能捕捉到运行时异常(无法将其转换到NSDictionary),那就更好了,真不敢相信他们不得不添加一个全新的关键字guard来实现这一点。使用大写字母作为变量名是个坏主意,你会让人困惑。但同时,感谢您的回答。如果变量是首字母缩略词(例如JSON、URL等),我更喜欢将整个单词大写,否则它看起来很奇怪(JSON、URL)
extension NSJSONSerialization{
    public class func dictionaryWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> NSDictionary{
        guard let d: NSDictionary = try self.JSONObjectWithData(data, options:opt) as? NSDictionary else{
            throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotParseResponse, userInfo: [NSLocalizedDescriptionKey : "not a dictionary"])
        }
        return d;
    }
}
{
"glossary":{
"title":"example glossary",
"GlossDiv":{
    "title":"S",
    "GlossList":{
        "GlossEntry":{
            "ID":"SGML",
            "SortAs":"SGML",
            "GlossTerm":"Standard Generalized Markup Language",
            "Acronym":"SGML",
            "Abbrev":"ISO 8879:1986",
            "GlossDef":{
                "para":"A meta-markup language, used to create markup languages such as DocBook.",
                "GlossSeeAlso":[
                                "GML",
                                "XML"
                                ]
            },
            "GlossSee":"markup"
        }
    }
}
}
}
extension JSONSerialization {

enum Errors: Error {
    case NotDictionary
    case NotJSONFormat
}

public class func dictionary(data: Data, options opt: JSONSerialization.ReadingOptions) throws -> NSDictionary {
    do {
        let JSON = try JSONSerialization.jsonObject(with: data , options:opt)
        if let JSONDictionary = JSON as? NSDictionary {
            return JSONDictionary
        }
        throw Errors.NotDictionary
    }
    catch {
        throw Errors.NotJSONFormat
    }
}
}
 func readJsonFromFile() {
    if let path = Bundle.main.path(forResource: "data", ofType: "json") {
        if let data = NSData(contentsOfFile: path) as? Data {

            do {
                let dict = try JSONSerialization.dictionary(data: data, options: .allowFragments)
                print(dict)
            } catch let error {
                print("\(error)")
            }

        }
    }
}
let jsonData = Data()
do {
    guard let parsedResult = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? NSDictionary else {
        return
    }
    print("Parsed Result: \(parsedResult)")
} catch {
    print("Error: \(error.localizedDescription)")
}