Error parsing a Json

1

When I parse a Json downloaded from here I get the following error:

  

Error: Error Domain = NSCocoaErrorDomain Code = 3840 "Unterminated string   around character 6464. "UserInfo = {NSDebugDescription = Unterminated   string around character 6464.} Error: Error Domain = NSCocoaErrorDomain   Code = 3840 "JSON text did not start with array or object and option to   allow fragments not set. "UserInfo = {NSDebugDescription = JSON text did   not start with array or object and option to allow fragments not set.}

I do not understand why, but following these steps:

  • I open the application (on a virtual iPhone)
  • I enter an input ( id ) so the page looks for me in the URL I need.
  • I miss the error.
  • Now, if I do it again with the same id the error does not come out anymore. If I use another id the next time, I will jump again until I repeat it again with the previous id .

    Code:

    class SearchPokemonDaoJson: NSObject,SearchPokemonDao, NSURLSessionDataDelegate {
    
        private let POKE_API = "http://pokeapi.co/api/v1/pokemon"
        private var session: NSURLSession = NSURLSession()
        private var task: NSURLSessionTask?
    
        private var hasFinished = 0
        private var pokemon: Pokemon?
    
        override init() {
            super.init()
            let config = NSURLSessionConfiguration.defaultSessionConfiguration()
            session = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue())
        }
    
        func search(ByID id: Int) -> Pokemon? {
            downloadBaseJson(NSURL(string: "\(POKE_API)/\(id)/")!)
            let before = CFDateGetAbsoluteTime(NSDate())
            while hasFinished != 2 {
                if ( (CFDateGetAbsoluteTime(NSDate()) - before) > 12000000000) {//5 Segundos.
                    return nil
                }
            }
            return pokemon
        }
    
        func search(ByName name: String) -> Pokemon? {
            downloadBaseJson(NSURL(string: "\(POKE_API)/\(name)/")!)
            let before = CFDateGetAbsoluteTime(NSDate())
            while hasFinished != 2 {
                if ( (CFDateGetAbsoluteTime(NSDate()) - before) > 12000000000) {//5 Segundos.
                    return nil
                }
            }
            return pokemon
        }
    
        private func makePokemon(From jsonDictionary: [String:AnyObject]) -> Pokemon? {
            let pokemonName = jsonDictionary["name"] as! String
            let pokemonID = jsonDictionary["national_id"] as! Int
            let pokemonTypes = convertTypes(jsonDictionary)
            downloadImageJson(extractSpriteURL(From: jsonDictionary)!)//Empieza a descargar el json de la imagen.
            let pokemon = Pokemon(id: pokemonID, type: pokemonTypes, name: pokemonName, goodAgainst: [PokemonType.Water], badAgainst: [PokemonType.Water])
            pokemon.evolution = extractEvolution(jsonDictionary)
            return pokemon
        }
    
        private func extractSpriteURL(From jsonDictionary: [String:AnyObject]) -> NSURL? {
            if let spritesArray = jsonDictionary["sprites"] {
                if let mainSprite = spritesArray[0] as? [String:String] {
                    if let mainUrl = mainSprite["resource_uri"] {
                        return NSURL(string: "http://pokeapi.co\(mainUrl)")
                    }
                }
            }
            return nil
        }
    
        private func convertTypes(jsonDictionary: [String:AnyObject]) -> [PokemonType] {
            var pokemonTypesS: [String] = []
            var arrayTypes = jsonDictionary["types"] as! Array<AnyObject>
            for index in 0..<arrayTypes.count {
                if let typeDictionary = arrayTypes[index] as? [String:AnyObject] {
                    if let typeInfo = typeDictionary["name"] as? String {
                        pokemonTypesS.append(typeInfo)
                    }
                }
            }
            return convertToArray(pokemonTypesS)
        }
    
        private func extractEvolution(jsonDictionary: [String:AnyObject] ) -> String? {
            if let evolutions = jsonDictionary["evolutions"] as? Array<AnyObject> {
                if !evolutions.isEmpty {
                    if let evolution = evolutions[0] as? [String:AnyObject] {
                        if let evolutionTo = evolution["to"] as? String {
                            return evolutionTo
                        }
                    }
                }
            }
            return nil
        }
    
        private func downloadImageJson(url: NSURL) {
            let task = session.dataTaskWithURL(url)
            task.taskDescription = "downloadPokemonImageJson"
            task.resume()
        }
    
        private func downloadImage(url:NSURL) {
            let task = session.dataTaskWithURL(url)
            task.taskDescription = "downloadPokemonImage"
            task.resume()
        }
    
        private func downloadBaseJson(url:NSURL) {
            hasFinished = 0
            task = session.dataTaskWithURL(url)
            task?.taskDescription = "downloadPokemonJson"
            task?.resume()
        }
    
    
    
        func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
            if dataTask.taskDescription == "downloadPokemonJson" {
                do {
                    let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves) as? [String:AnyObject]
                    pokemon = makePokemon(From: jsonDictionary!)
                    self.hasFinished += 1
                } catch let error {
                    print("Error: \(error)")
                }
    
            } else if dataTask.taskDescription == "downloadPokemonImageJson" {
                do {
                    if let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves) as? [String:AnyObject] {
                        if let url = jsonDictionary["image"] as? String {
                            downloadImage(NSURL(string: "http://pokeapi.co\(url)")!)
                        }
                    }
                } catch let error {
                    print("Error extrayendo el main url para el sprite. \(error) ")
                }
            } else if dataTask.taskDescription == "downloadPokemonImage" {
                if let pokemon = pokemon {
                    pokemon.sprite = UIImage(data: data)
                    self.hasFinished += 1
                }
            }    }
    
        func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
            if task.taskDescription == "downloadPokemonJson" {
                if error != nil {
                    print("Terminó de descargar la data con un error: \(error?.localizedDescription)")
                }
            }
        }
    
        func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {//error
            if (error != nil) {
                print("Error descargando el json de pokeapi: \(error?.description)")
            }
        }
    
    }
    
        
    asked by MatiEzelQ 18.08.2016 в 01:54
    source

    1 answer

    2

    It gives an error at the beginning because you are trying to use the JSON without it being completely downloaded.

    Usually an asynchronous download is used, and an operation called callback is executed.

    Another way is to make a timer, wait for so many seconds and try to pause again, with try / catch ... You can try it as many times as you want with a while , until the file is completely downloaded.

        
    answered by 23.01.2018 в 17:46