2016-09-20 44 views
1

我剛從Swift轉換我的項目2.2到3.0,我得到一個新的異常拋出我的測試。我有一些Objective C的代碼在我的測試中一個從一個文件中的某些JSON寫着:Swift 3 NSDictionary to Dictionary conversion causes NSInvalidArgumentException

+ (NSDictionary *)getJSONDictionaryFromFile:(NSString *)filename { 
    /* some code which checks the parameter and gets a string of JSON from a file. 
    * I've checked in the debugger, and jsonString is properly populated. */ 

    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; 
    return jsonDict; 
} 

我從一些銀行代碼調用此:

let expectedResponseJSON = BZTestCase.getJSONDictionary(fromFile: responseFileName) 

這只是正常最時間,但我有一個JSON文件,導致該錯誤:

failed: caught "NSInvalidArgumentException", "-[__NSSingleObjectArrayI enumerateKeysAndObjectsUsingBlock:]: unrecognized selector sent to instance 0x608000201fa0" 

關於這個奇怪的是,生成該錯誤的在填充Swift代碼之前,在getJSONDictionaryFromFile方法返回並在expectedResponseJSON之前。對我而言,這似乎是說,它是從NSDictionaryDictionary這是問題的轉換。違規的JSON文件是這個:

[ 
    { 
    "status": "403", 
    "title": "Authentication Failed", 
    "userData": {}, 
    "ipRangeError": { 
     "libraryName": "Name goes here", 
    "libraryId": 657, 
     "requestIp": "127.0.0.1" 
    } 
    } 
] 

如果我去掉最外層的[],該錯誤消失。我不能成爲Swift 3中唯一使用數組作爲JSON文件的頂層實體的人,我做錯了什麼?我能做些什麼來解決這個錯誤?

+0

當然,您可以使用數組作爲頂級JSON對象。但是,你必須把它看作一個數組,而不是字典。 –

回答

4

正如在評論中提到的那樣,問題是getJSONDictionaryFromFile返回NSDictionary *而我的JSON輸入是一個數組。唯一的謎就是爲什麼這個在Swift 2.2中起作用!我最終改變expectedResponseJSON是一個Any?,並重寫了斯威夫特我的目標C代碼:

class func getStringFrom(file fileName: String, fileExtension: String) -> String { 
    let filepath = Bundle(for: BZTestCase.self).path(forResource: fileName, ofType: fileExtension) 
    return try! NSString(contentsOfFile: filepath!, usedEncoding: nil) as String 
} 

class func getJSONFrom(file fileName: String) -> Any? { 
    let json = try! JSONSerialization.jsonObject(with: (getStringFrom(file: fileName, fileExtension: ".json").data(using: .utf8))!, options:.allowFragments) 
    return json 
} 

作爲一個說明,任何人誰可能剪切和粘貼這段代碼,我用try!filepath!代替try?if let...因爲此代碼僅用於測試,因此如果我的輸入不是我期望的那樣,我希望它儘快崩潰。