Разбор ответа JSON с использованием Codable дает ошибку в swift - PullRequest
0 голосов
/ 09 февраля 2019

Я пытаюсь проанализировать ответ JSON с помощью Codable, но он выдает ошибку.Я попытался сослаться из ссылки на переполнение стека, но ничего не вышло. как мне разобрать любое в словаре с помощью 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информация из этого ответа - полное имя, URL-адрес HTML и последователи.Ссылка для веб-API

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

Пожалуйста, ознакомьтесь с кодом.

Ниже приведено сообщение об ошибке:

*От 1018 * '__ NSDictionaryI' (0x102965a98) до 'NSData' (0x102964580).2019-02-09 16: 17: 42.062971 + 0530 PhotoViewwer [13342: 259997] Не удалось преобразовать значение типа «__NSDictionaryI» (0x102965a98) в «NSData» (0x102964580).

Спасибо

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Пожалуйста, научитесь читать JSON.Это довольно легко.Существует только два типа коллекций, массив ([]) и словарь ({})

Ваши структуры неверны.

В корневом словаре JSON есть массив словарейдля ключа items.
В каждом словаре есть ключи full_name и owner ( здесь - это структура 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 struct членов

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 для NSURL и 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()
}
0 голосов
/ 09 февраля 2019

Вам нужно

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)

, так как это приведет к сбою

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...