使用Codable解析JSON响应会迅速出错

时间:2019-02-09 10:21:56

标签: ios json swift parsing

我正在尝试使用Codable解析JSON响应,但这给了我错误。 我试图从下面的堆栈溢出链接引用,但没有用。 how do I parse Any in dictionary using swift

下面是我的代码,不确定在哪里我错了。

> 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 url和关注者。 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)。

谢谢

2 个答案:

答案 0 :(得分:2)

请学习阅读JSON。很简单集合类型只有两种,数组([])和字典({}

您的结构错误。

在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情况返回所有 real 错误。 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...类,这里URL代表NSURLURLRequest代表NS(Mutable)URLRequest

答案 1 :(得分:1)

您需要

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)

因为它会崩溃