如何使用URLSession从URL获取JSON数据?

5

我正在开发一款iOS应用程序,需要从此URL获取数据。

据我所见,这个URL包含JSON数据,我不知道是否需要解析它,也不知道如何获取这些JSON数据。

以下是我的代码:

import UIKit
import SwiftyJSON

typealias ServiceResponse = (ApiResponseData, NSError?) -> Void

class ApiManager: NSObject {

    var session:URLSession? = nil
    var urlRequest:URLRequest? = nil

    override init(){
        super.init()

        urlRequest = URLRequest(url: URL(string:"https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json")!)
        urlRequest?.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
        session = URLSession(configuration: .default)

    }

    func callRestApiToFetchDetails(onCompletion: @escaping ServiceResponse) {
        let task = session?.dataTask(with: urlRequest!, completionHandler: {data, response, error -> Void in
            print("Response = \(data)")

            do {
                let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                // Do Stuff
                print("\(jsonData)")
            } catch {
                // handle error
            print("Error in parsing - \(error)")
            }
        })
        task?.resume()
    }
}

但是我在解析时遇到错误。

在这里输入图片描述


尝试在try catch块中打印错误} catch (let error) { print("解析错误 - \(error)") - Lukas Würzburger
1
@lufritz 不需要 (let error) 部分,catch 块会自动创建一个 error 变量,所以你可以直接写 catch { print(error)} - Dávid Pásztor
1
不相关,但您的代码存在几个概念问题。如果您在初始化程序中肯定会为其分配非可选值,则不要将值初始化为可选项。此外,在初始化程序内部分配硬编码值是没有必要的,这不是 Obj-C,在 Swift 中,您也可以在初始化程序之外将对象分配给变量。此外,没有必要从“NSObject”继承,在 Swift 类中不需要有基类。 - Dávid Pásztor
1
@ajeetsharma 如果你想使用SwiftyJSON框架(我建议在Swift 4中使用Codable协议),为什么不使用它的方法来解码JSON响应呢? - Dávid Pásztor
@DávidPásztor 如何使用SwifyJSON?实际上,我尝试使用cocoapods并添加了这个框架,但是在SwiftyJSON中我遇到了相同的问题。 - ajeet sharma
显示剩余2条评论
1个回答

4
您的 Web 服务响应是 String.Encoding.ascii,在通过 NSDictionary JSONSerialization 转换之后转换为 String.Encoding.utf8。尝试使用此方法来解决问题。
  let url = "https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json"
    URLSession.shared.dataTask(with: URL(string: url)!) { (data, res, err) in

        if let d = data {
            if let value = String(data: d, encoding: String.Encoding.ascii) {

                if let jsonData = value.data(using: String.Encoding.utf8) {
                    do {
                        let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as! [String: Any]

                        if let arr = json["rows"] as? [[String: Any]] {
                            debugPrint(arr)
                        }

                    } catch {
                        NSLog("ERROR \(error.localizedDescription)")
                    }
                }
            }

        }
        }.resume()

它可以工作,但我们是否有其他简单的方法来解析它?有没有更短的代码可用? - ajeet sharma
2
不要在Swift中使用NSDictionary,也不要显式调用init方法。 - Dávid Pásztor
1
同时在Swift中不要使用.mutableLeaves,因为它没有意义。在声明变量时,您可以使用letvar关键字来控制可变性。 - Dávid Pásztor
你可以使用SwiftyJSON。如果我的回答正确,请打勾或点赞。谢谢。 - AshvinGudaliya
必须阅读NSJSONSerialization Fails with Unicode这个苹果论坛中的相同问题。看起来是服务器端的问题。JSON需要用UTF-8编码,但您的服务器似乎正在以其他编码发送它。 - AshvinGudaliya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接