使用 Alamofire 和 Swift 3 反序列化复杂的 JSON

Posted

技术标签:

【中文标题】使用 Alamofire 和 Swift 3 反序列化复杂的 JSON【英文标题】:Deserialize complex JSON using Alamofire and Swift 3 【发布时间】:2017-05-26 09:39:47 【问题描述】:

如何反序列化这个 JSON 并在 tableView 中显示标题 JSON:https://www.healthcare.gov/api/articles.json

到目前为止我所尝试的:

struct  News 
    let title : String

    init(dictionary: [String:String]) 
        self.title = dictionary["mainTitle"] ?? ""
    


var newsData = [News]()

func downloadData() 
    Alamofire.request("https://www.healthcare.gov/api/articles.json").responseJSON  response in
        print(response.request as Any)
        print(response.response as Any)
        print(response.data as Any)
        print(response.result.value)

        self.newsData.removeAll()
        if let json = response.result.value as? [[String:String]] 
            for news in json 
                self.newsData.append(News(dictionary: news))
            
            self.tableView.reloadData()
        
    


override func viewDidLoad() 
    super.viewDidLoad()
      downloadData()


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()


override func numberOfSections(in tableView: UITableView) -> Int 
    return 1


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return newsData.count


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    let news = newsData[indexPath.row]
    cell.textLabel?.text = news.title
    return cell

服务器状态码是 200,所以我知道我的请求没问题。问题是我不知道如何创建合适的数据模型。

【问题讨论】:

【参考方案1】:

JSON 令人困惑,因为在 articles 数组的末尾(应该只包含字典)有一个布尔值 false,因此向下转换为 [[String:Any]] 失败。

你必须flatMap数组忽略Bool

    if let json = response.result.value as? [String:Any],
       let articles = json["articles"] as? [Any] 
           for news in articles.flatMap($0 as? [String:Any]) 
               self.newsData.append(News(dictionary: news))
           
           self.tableView.reloadData()
    

并且键mainTitle在JSON中不存在,在Newsinit方法中你必须写(字典是[String:Any]而不是[string:String]

init(dictionary: [String:Any]) 
    self.title = dictionary["title"] ?? ""

【讨论】:

你对parsedData是什么意思,它不存在但你把它分配给文章,编译器不让我运行它。 但是现在我的应用程序崩溃了,因为在这一行展开时有一个 nil self.newsData.append(News(dictionary: news as! [String : String] )) 字典是[String:Any]。我更新了答案。并删除强制向下转换。【参考方案2】:

为了快速处理 JSON,我建议你使用 SwiftyJSON。 (https://github.com/SwiftyJSON/SwiftyJSON)

var myJson : JSON
func downloadData() 
    Alamofire.request("https://www.healthcare.gov/api/articles.json").responseJSON  response in
        print(response.request as Any)
        print(response.response as Any)
        print(response.data as Any)
        print(response.result.value)
        self.myJson = JSON(response.result.value)
        self.tableView.reloadData()
    

现在您可以遍历 myJson 并调整 tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) 以检索您的结果

【讨论】:

但是我怎样才能只提取标题呢?此外,您正在分配没有 JSON 信息的 response.result,它只有服务器标头。 JSON 可以在 response.result.value 下找到,但我不需要遍历整个数组,我只需要标题。【参考方案3】:

用这个替换你的函数。

func downloadData() 
            Alamofire.request("https://www.healthcare.gov/api/articles.json").responseJSON  response in
                print(response.request as Any)
                print(response.response as Any)
                print(response.data as Any)
                print(response.result.value)

                self.newsData.removeAll()
                if let json = response.result.value as? [String:AnyObject]  //As outermost object in your JSON file is a dictionary
                
                    let article = json["articles"] as? [[String:AnyObject]] //Here you need to get inner object which is value for key "articles"
                    for news in article 
                        self.newsData.append(News(dictionary: news))
                    
                    self.tableView.reloadData()
                
            
        

您可以在http://www.jsoneditoronline.org/获得可读的 JSON

【讨论】:

【参考方案4】:

尝试将您的响应映​​射到数据模型。然后你不需要反序列化你的 json。 https://github.com/insanoid/SwiftyJSONAccelerator 将帮助您创建数据模型。

【讨论】:

你说Try to map your response to a data model. 但 OP 已经在说“问题是我不知道如何创建合适的数据模型”。他们已经知道他们应该这样做。他们在问如何做到这一点。

以上是关于使用 Alamofire 和 Swift 3 反序列化复杂的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3 的 ObjectMapper 和 Alamofire 问题 Alamofire 4 的 Alamofire 版本

使用 Swift 3 拉动刷新和 Alamofire

带有 XML 响应和正文的 SOAP 请求 swift 3,Alamofire

JSON:使用 Alamofire 和 Swift 3 提取数据

使用 Alamofire 和 Mapkit Swift 3 请求

使用 Swift 3 和 Alamofire 上传文件