簡體   English   中英

使用Codable解析JSON響應會在swift中產生錯誤

[英]Parsing JSON response using Codable gives error in swift

我正在嘗試使用Codable解析JSON響應,但它給了我錯誤。 我試圖從下面的堆棧溢出鏈接引用,但沒有工作。 如何使用swift解析字典中的Any

下面是我的代碼,不知道我在哪里錯了。

> enum JSONError: String,Error {
>         case NoData = "ERROR: no data"
>         case ConversionFailed = "ERROR: conversion from JSON failed"
>     }

struct Owner : Decodable {
    let full_name : String
    let html_url:String
    let follower:follower
}

struct follower : Decodable {
    let followers_url : String
}


func jsonParser() {
        let urlPath = "https://api.github.com/search/repositories?q=language:ruby&sort=stars&order=desc"
        guard let endpoint = NSURL(string: urlPath) else {
            print("Error creating endpoint")
            return
        }

        let request = NSMutableURLRequest(url:endpoint as URL)
        URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
            do {
                guard let data = data else {
                    throw JSONError.NoData
                }

                let jsonResponse = try JSONSerialization.jsonObject(with:
                    data)

                let entries = try! JSONDecoder().decode([Owner].self, from: jsonResponse as! Data)
                print(jsonResponse)
            } catch let error as JSONError {
                print(error.rawValue)
            } catch let error as NSError {
                print(error.debugDescription)
            }
            }.resume()
    }

我需要從此響應中獲取3個信息 - 全名,html網址和關注者。 鏈接web api

https://api.github.com/search/repositories?q=language:ruby

請最新看一下代碼。

以下是錯誤消息:

'__NSDictionaryI'(0x102965a98)到'NSData'(0x102964580)。 2019-02-09 16:17:42.062971 + 0530 PhotoViewwer [13342:259997]無法將'__NSDictionaryI'(0x102965a98)類型的值轉換為'NSData'(0x102964580)。

謝謝

請學習閱讀JSON。 這很容易。 只有兩種集合類型,array( [] )和dictionary( {}

你的結構是錯誤的。

在JSON的根詞典中,有一系列關鍵items的字典。
在每個字典中都有鍵full_nameowner這里Owner結構的位置)。
密鑰follower的字典存在。

這些結構正確地代表了JSON

struct Response : Decodable {
    let items : [Item]
}

struct Item : Decodable {
    let fullName : String
    let owner : Owner
}

struct Owner : Decodable {
    let htmlUrl : URL // URL strings can be decoded directly into URL
    let followersUrl : URL
}

在函數中添加一個完成處理程序,並使用枚舉作為結果類型。 failure案例會返回所有真實錯誤。 URLRequest是多余的。 只需傳遞URL即可。 JSONSerialization系列毫無意義。

convertFromSnakeCase策略將基於snake_cased的鍵轉換為camelCased結構成員

enum Result {
    case success(Response), failure(Error)
}

func jsonParser(completion: @escaping (Result) -> Void) {
    let endpoint = URL(string:"https://api.github.com/search/repositories?q=language:ruby&sort=stars&order=desc")!
    URLSession.shared.dataTask(with: endpoint) { (data, response, error) in
        if let error = error { completion(.failure(error)); return }
        do {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            let entries = try decoder.decode(Response.self, from: data!)
            completion(.success(entries))
        } catch {
            completion(.failure(error))
        }
    }.resume()
}

並稱之為

jsonParser { result in
    switch result {
    case .success(let entries) : print(entries)
    case .failure(let error) : print(error)
    }
}

基本上從不使用NS...類,如果有本機等價物,這里NSURL URLNS(Mutable)URLRequest URLRequest NS(Mutable)URLRequest

編輯:

在Swift 5中,使用本機Result類型語法變得更加方便。 它能夠轉換投擲表達式

 
 
 
  
  enum Result { case success(Response), failure(Error) }
 
  

func jsonParser(completion: @escaping (Result<Response,Error>) -> Void) {
    let endpoint = URL(string:"https://api.github.com/search/repositories?q=language:ruby&sort=stars&order=desc")!
    URLSession.shared.dataTask(with: endpoint) { (data, response, error) in
        if let error = error { completion(.failure(error)); return }

        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        completion(Result{ try decoder.decode(Response.self, from: data!) })

    }.resume()
}

你需要

func jsonParser() {
    let urlPath = "https://api.github.com/search/repositories?q=language:ruby&sort=stars&order=desc"
    guard let endpoint = NSURL(string: urlPath) else {
        print("Error creating endpoint")
        return
    }

    let request = NSMutableURLRequest(url:endpoint as URL)
    URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
        do {

            let dec = JSONDecoder()
            dec.keyDecodingStrategy = .convertFromSnakeCase
            let entries = try dec.decode(Root.self, from:data!)
            print(entries)
        } catch {
            print(error)
        }
        }.resume()
}

struct Root : Decodable {
    let items:[Item]
}
struct Owner: Codable {
    let login: String
    let id: Int
    let nodeId: String
    let avatarUrl: String
    let gravatarId: String
    let url, htmlUrl, followersUrl: String
    let followingUrl, gistsUrl, starredUrl: String
    let subscriptionsUrl, organizationsUrl, reposUrl: String
    let eventsUrl: String
}

struct Item: Codable {
    let fullName : String
    let htmlUrl:String
    let owner: Owner
}

您不應該在此處轉換對數據的響應

from: jsonResponse as! Data)

因為它會崩潰

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM