【问题标题】:Error while parsing JSON data received via Alamofire (Swift)解析通过 Alamofire (Swift) 接收的 JSON 数据时出错
【发布时间】:2018-10-19 05:04:04
【问题描述】:

我正在与一家非营利组织合作,帮助他们为其网站开发移动应用程序(因此他们为我提供了后端服务等)

他们的登录 PHP 服务接受 JSON 格式的数据,并以 JSON 数据的形式返回 true 或 false 值,但我在 Swift 中处理响应时遇到了问题。我正在使用 Alamofire 连接到 HTTP 服务。

我正在附上我的代码和我在下面收到的异常消息,非常感谢一些帮助

func authenticateUser (un: String, pw: String)  -> Bool
{
    var checker = false
    let jsonDict : [String: String] = ["volunteer_email": un, "volunteer_pass": pw]

     Alamofire.request("www.sampleurl.com/login.php", method: .post, parameters: jsonDict, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in

        switch(response.result) {
        case .success(_):
            if response.result.value != nil{
                print (response.result.value)
                let resp = response.result.value as! NSDictionary
                let results = resp["status"] as! [[String:Any]]
                //Change the boolean value of checker based on the value of the results constant
                print (results)
            }
            break

        case .failure(_):
            print(response.result.error)
            break
        }
    }

    return checker;
}

日志:

可选(<__nssingleobjectarrayi>( { 状态=假; } ) ) 无法将“__NSSingleObjectArrayI”(0x10e28c528)类型的值转换为“NSDictionary” (0x10e28d1a8)。 2018-05-09 12:13:00.177091+0530 TestApp1 [16680:817883] 无法将“__NSSingleObjectArrayI”(0x10e28c528)类型的值转换为 'NSDictionary' (0x10e28d1a8)。 (lldb)

result.result.value 的日志:

注意:"status":"false"/"true" 是网络服务的输出

可选(<__nssingleobjectarrayi>( { 状态=假; } ))

注意:我做了一些研究,了解 NSSingleObjectArray 是什么以及导致它的原因,但我被困在这里,因为该服务只将一个 JSON 值传回我的应用程序。有没有办法在不要求组织更改代码的情况下处理这个问题?从逻辑上讲,我是否应该能够将响应转换为 NSDictionary 而不管其大小?

另外,我之所以指定返回的数据可以是 any 类型,是因为我遇到了一个可以在这里找到的问题:

Other StackOverflow question

提前非常感谢:)

【问题讨论】:

  • 这是斯威夫特。不要使用 NSDictionary 或其他 Objective-C 集合类型。
  • 尝试将这一行 let resp = response.result.value as! NSDictionary 编辑为 let resp = response.result.value as! NSArray
  • @a.masri 不要使用NSArray。使用 Swift 数组。并避免强制施法。安全施放。
  • github.com/SwiftyJSON/SwiftyJSON搭配alamofire,很有用
  • @ShubhamNaik 如果有人无法区分 JSON 数组和字典,则解析工具无关紧要。

标签: ios json swift alamofire


【解决方案1】:

由于您使用的是 Alamofire 的 .responseJSON,因此您应该使用 Alamofire 的参数化枚举。它在.success 中提供了 json 对象。所以case .success(_) 是浪费。

继续这个,根本不需要类型转换response.result.value

Alamofire
    .request("www.sampleurl.com/login.php",
             method: .post,
             parameters: jsonDict,
             encoding: JSONEncoding.default,
             headers: nil)
    .responseJSON { (response) in            
        switch(response.result) {
        case .success(let responseJSON):
            print(responseJSON)

            /*
             As an improvement:
             To obtain an easy-access object, convert responseJSON to either a:
              1. Codable model:
                 let model = JSONDecoder().decode(SomeModel.self, 
                                                  from: responseJSONData)
              2. SwiftyJSON object: (available on GitHub)
                 let json = JSON(responseJSON)

             Doing so will basically make accessing the inner elements easier.
             */...

        case .failure(let error):
            print(error)
        }
}

顺便说一句,仅供参考:响应是一个字典数组,而不是字典数组的字典。

【讨论】:

  • 当涉及到从远程源获取 JSON 数据时,您不应该强制转换或做出其他假设。您永远不知道服务器何时可能返回意外数据。始终进行防御性编码。比让用户崩溃的应用程序更好地处理意外数据。
  • 没用,我得到了这个:线程 1:EXC_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0)。我理解你的逻辑,谢谢!但问题仍然存在:/
  • 在我发布产品之前肯定会进行防御性编码,老实说,只是想现在就开始工作
  • @rmaddy 谢谢。我知道。对于答案,根据 OP 的上下文,我会效仿并就强制解包提出免责声明。显示可选绑定有时只会增加答案和解释。
  • @Raghav 它在哪里崩溃?是强行解开吗?可选地将它与as? 绑定,如果它有效,那么告诉我们print (response.result.value) 记录了什么
【解决方案2】:

使用 NSArray 代替 NSDictionary

func authenticateUser (un: String, pw: String)  -> Bool{
var checker = false
let jsonDict : [String: String] = ["volunteer_email": un, "volunteer_pass": pw]

 Alamofire.request("www.sampleurl.com/login.php", method: .post, parameters: jsonDict, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in

    switch(response.result) {
    case .success(_):
        if response.result.value != nil{
            print (response.result.value)
            let resp = response.result.value as! NSArray
            let results = resp["status"] as! [[String:Any]]
            //Change the boolean value of checker based on the value of the results constant
            print (results)
        }
        break

    case .failure(_):
        print(response.result.error)
        break
      }
   }

return checker;
 }

【讨论】:

  • 这是 Swift:使用 Swift。使用 Swift 类型数组而不是 Foundation 的 NSArray。
  • 使用 NSArray 也会抛出异常,我试过了。无论如何感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
相关资源
最近更新 更多