Swift - Error de análisis de datos - Swift.DecodingError.dataCorrupted

Oct 09 2020

Estoy usando SwiftSoup en combinación con Codable para obtener los elementos correctos y analizar los datos. Sin embargo, recibo este error:

JSON decode failed: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.})))

Busqué en línea, me aseguré de que mis datos coincidan correctamente, incluso cambié los tipos esperados de Int a String, pero obtuve un error que indica que se esperaba un Int.

Estos son los datos que estoy recibiendo y puedo imprimir en la consola:

data - 
{"test":0,"ppace":85,"pshooting":92,"ppassing":91,"pdribbling":95,"pdefending":38,"pphysical":65,"acceleration":91,"sprintspeed":80,"agility":91,"balance":95,"reactions":94,"ballcontrol":96,"dribbling":96,"positioning":93,"finishing":95,"shotpower":86,"longshotsaccuracy":94,"volleys":88,"penalties":75,"interceptions":40,"headingaccuracy":70,"marking":32,"standingtackle":35,"slidingtackle":24,"vision":95,"crossing":85,"freekickaccuracy":94,"shortpassing":91,"longpassing":91,"curve":93,"jumping":68,"stamina":72,"strength":69,"aggression":44,"composure":96}

Esta es mi función:

 func parseData() {
    do {
    let html = try String(contentsOf: url!, encoding: String.Encoding.ascii)
        let doc: Document = try! SwiftSoup.parse(html)
        let elements = try doc.getAllElements()
        for element in elements {
            switch element.id() {
            case "player_stats_json":
              
                let content = try! element.getElementsContainingText("ppace").text()
                print(content.utf8)
                let jsonData = content.data(using: .utf8)
                    do {
                        self.player = try JSONDecoder().decode(PlayerModel.self, from: Data(jsonData!))
                    } catch let jsonError as NSError {
                        print("JSON decode failed: \(jsonError)")
                        print("data - \(content)")
                    }
            default:
                break
            }
        }

    } catch Exception.Error(type: let type, Message: let message) {
        print(type)
        print(message)
    } catch {
        print("")
    }
    }

Y este es mi archivo de modelo:

struct PlayerModel: Codable {
    var test: Int
    var ppace: Int
    var pshooting: Int
    var ppassing: Int
    var pdribbling: Int
    var pdefending: Int
    var pphysical: Int
    var acceleration: Int
    var sprintspeed: Int
    var agility: Int
    var balance: Int
    var reactions: Int
    var ballcontrol: Int
    var dribbling: Int
    var positioning: Int
    var finishing: Int
    var shotpower: Int
    var longshotsaccuracy: Int
    var volleys: Int
    var penalties: Int
    var interceptions: Int
    var headingaccuracy: Int
    var marking: Int
    var standingtackle: Int
    var slidingtackle: Int
    var vision: Int
    var crossing: Int
    var freekickaccuracy: Int
    var shortpassing: Int
    var longpassing: Int
    var curve: Int
    var jumping: Int
    var stamina: Int
    var strength: Int
    var aggression: Int
    var composure: Int
}

He comprobado dos y tres veces que los nombres de las variables coincidan con cada tecla. He pegado los datos generados en la consola en un validador JSON en línea y no aparecen errores. Realmente me he quedado rascándome la cabeza ahora mismo, porque no puedo entender dónde me he equivocado.

Respuestas

2 LeoDabus Oct 09 2020 at 21:25

Todavía no tengo idea de qué pasa con su análisis. Me las arreglé para analizar su html pero no tengo idea de por qué al intentar usar Int en lugar de Uint8 seguía sin devolver los valores correctos. Esto es lo que funcionó para mí:

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
struct PlayerModel: Codable {
    let test: UInt8
    let ppace: UInt8
    let pshooting: UInt8
    let ppassing: UInt8
    let pdribbling: UInt8
    let pdefending: UInt8
    let pphysical: UInt8
    let acceleration: UInt8
    let sprintspeed: UInt8
    let agility: UInt8
    let balance: UInt8
    let reactions: UInt8
    let ballcontrol: UInt8
    let dribbling: UInt8
    let positioning: UInt8
    let finishing: UInt8
    let shotpower: UInt8
    let longshotsaccuracy: UInt8
    let volleys: UInt8
    let penalties: UInt8
    let interceptions: UInt8
    let headingaccuracy: UInt8
    let marking: UInt8
    let standingtackle: UInt8
    let slidingtackle: UInt8
    let vision: UInt8
    let crossing: UInt8
    let freekickaccuracy: UInt8
    let shortpassing: UInt8
    let longpassing: UInt8
    let curve: UInt8
    let jumping: UInt8
    let stamina: UInt8
    let strength: UInt8
    let aggression: UInt8
    let composure: UInt8
}

let url = URL(string:"https://www.futbin.com/21/player/541/lionel-messi")!
URLSession.shared.dataTask(with: url) { data, response, error in
    guard let data = data, let html = String(data: data, encoding: .utf8) else { return }
    if let start = html.range(of: #"<div style="display: none;" id="player_stats_json">"#)?.upperBound,
       let end = html[start...].range(of: #"</div>"#)?.lowerBound {
        let json = html[start..<end]
        do {
            let player = try JSONDecoder().decode(PlayerModel.self, from: Data(json.utf8))
            print(player)
        } catch {
            print(error)
        }
    }
}.resume()

Esto imprimirá

PlayerModel (prueba: 0, ppace: 85, pshooting: 92, ppassing: 91, pdribbling: 95, pdefending: 38, pphysical: 65, aceleración: 91, sprintspeed: 80, agilidad: 91, equilibrio: 95, reacciones: 94, control de balón: 96, regate: 96, posicionamiento: 93, remate: 95, potencia de disparo: 86, precisión de tiros lejanos: 94, voleas: 88, penaltis: 75, intercepciones: 40, precisión de cabeza: 70, marcaje: 32, entrada de pie: 35, entrada deslizante: 24, visión: 95, cruce: 85, precisión de tiros libres: 94, pases cortos: 91, pases largos: 91, curva: 93, saltos: 68, resistencia: 72, fuerza: 69, agresión: 44, compostura: 96)