Разрешить фрагменты JSON с помощью Decodable - PullRequest
0 голосов
/ 13 ноября 2018
import UIKit

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
    //@IBOutlet weak var ingredientText: UILabel!

    struct Recipes: Decodable {
        let recipe_id:String?
        let image_url:String?
        let source_url:String?
        let f2f_url:String?
        let title:String?
        let publisher:String?
        let social_rank:Float64?
        let page:Int?
        let ingredients:[String]?

        private enum CodingKeys: String, CodingKey{
            case recipe_id = "recipe_id"
            case image_url = "image_url"
            case source_url = "source_url"
            case f2f_url = "f2f_url"
            case title = "title"
            case publisher = "publisher"
            case social_rank = "social_rank"
            case page = "page"
            case ingredients = "ingredients"
        }
    }

    var recipes = [Recipes]()
    var food = "chicken"
    var food2 = "peas"
    var food3 = "onions"
    //var recipeData = [Recipe]

    @IBOutlet weak var tableView: UITableView!

    fileprivate func getRecipes() {
        let jsonURL = "http://food2fork.com/api/search?key=264045e3ff7b84ee346eb20e1642d9d9264045e3ff7b84ee346eb20e1642d9d9&food=chicken&food2=onions&food3=peas"

        guard let url = URL(string: jsonURL) else{return}

        URLSession.shared.dataTask(with: url) {(data, _ , err) in
            DispatchQueue.main.async {
                if let err = err{
                    print("failed to get data from URL",err)
                    return
                }
                guard let data = data else{return}

                do {
                    let decoder = JSONDecoder()
                    decoder.keyDecodingStrategy = .convertFromSnakeCase
                    self.recipes = try decoder.decode([Recipes].self, from: data)
                    self.tableView.reloadData()
                }catch let jsonERR {
                    print("Failed to decode",jsonERR)
                }
            }
        }.resume()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return recipes.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")

        let recipe = recipes[indexPath.row]
        cell.textLabel?.text = recipe.title
        return cell
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationItem.title = "Ingredients"
        getRecipes()
    }
}

Я получаю сообщение об ошибке:

Текст JSON не начинался с массива или объекта и параметр, позволяющий не задавать фрагменты. "UserInfo = {NSDebugDescription = Текст JSON не начинался смассив или объект и опция, позволяющая не устанавливать фрагменты.})))

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Вы хотите декодировать [Recipe], то есть Array из Recipe.Это означает, что первый (не пробельный) символ в data должен быть [ (чтобы сделать его массивом JSON), а это не так.Поэтому вам нужно выяснить, почему вы получаете неправильный ответ, и решить эту проблему.Попробуйте преобразовать data в String и распечатать его:

print(String(data: data, encoding: .utf8))
0 голосов
/ 13 ноября 2018

JSONDecoder не предоставляет JSONSerialization.ReadingOptions.

Вы можете вручную проверить, является ли первый байт данных открывающей квадратной скобкой <5b> или фигурной скобкой <7b>

guard let data = data, let firstByte = data.first else { return }
guard firstByte == 0x5b || firstByte == 0x7b else { 
    let string = String(data: data, encoding: .utf8)!
    print(string)
    return 
}

Однако я 'Рекомендуется использовать параметр response для проверки кода состояния 200

URLSession.shared.dataTask(with: url) { (data, response , error) in
    if let response = response as? HTTPURLResponse, response.statusCode != 200 {
        print(response.statusCode)
        return
    }
...

Примечание. Если CodingKeys точно соответствуют элементам структуры, вы можете опустить CodingKeys, и, поскольку вы явно используете .convertFromSnakeCase, вы используетеРекомендуется называть членов структуры recipeId, imageUrl, sourceUrl и т. д.

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