JSON "Недопустимое значение вокруг символа 0", хотя URL работает безупречно, и JSON действителен - PullRequest
0 голосов
/ 05 июня 2018

У меня есть эта ошибка json, которая, кажется, случайно появляется.

Я загружаю json из домена и анализирую его в словарь.Если ошибка не возникает, она работает безупречно.Вот код:

func retrieveCoinPairData() {

    guard !checkIfBaseAndTargetAreEqual() else { return }

    if let base = self.currentBase, let target = self.currentTarget {
        if let url = URL(string: "https://api.cryptonator.com/api/full/\(base.code)-\(target.code)") {

            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

                if let error = error {
                    print(error.localizedDescription)
                }
                if let response = response {
                    print("reponse /api/full", response)
                }
                do {
                    if let data = data {
                        let jsonData = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any]
                        self.createCoinPairData(with: jsonData)
                    } else {
                        self.delegate?.updateInfoLabelContent(content: .noInternetConnection)
                    }
                } catch {
                    self.delegate?.updateInfoLabelContent(content: .error)
                    print("catch error", error, data?.description as Any)
                    self.retrieveCoinPairData()
                }
            }).resume()
        } else {
            self.delegate?.updateInfoLabelContent(content: .error)
        }
    }
}

Ответ сервера следующий: выдается ошибка 403:

reponse /api/full <NSHTTPURLResponse: 0x608000232400> { 
URL: https://api.cryptonator.com/api/full/BTC-ETH } { 
status code: 403, headers {
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "text/html";
    Date = "Tue, 05 Jun 2018 04:23:37 GMT";
    "Keep-Alive" = "timeout=15";
    Server = nginx;
    "Transfer-Encoding" = Identit

, а ошибка перехвата URLSession следующая:

catch error Error Domain=NSCocoaErrorDomain Code=3840 
"Invalid value around character 0." 
UserInfo={NSDebugDescription=Invalid value around character 0.}
Optional("162 bytes")

Ошибка возникает в строке try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any].

Теперь в любое время эта ошибка возникает (и она совершенно случайная), когда я проверяю URL в браузере, она отлично работает.

Я проверил json с помощью jsonlint.com, и он действителен, нет объекта верхнего уровня, который бы требовал фрагментации json, хотя эта опция, казалось, уменьшала ошибку в прошлом.

Я знаю, что ошибка кода 403 говорит мне, что веб-сайт блокирует доступ, а ошибка кода 3840 говорит мне, что нет содержимого для анализа.Тем не менее, мне интересно, где и почему возникает ошибка.

Этот сайт используется в этом примере: https://api.cryptonator.com/api/full/btc-eth

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Существует перенаправление на URL, которое иногда происходит.Вы можете видеть перенаправление чего-то вроде ohio.something, когда вы запрашиваете URL.Когда происходит перенаправление, urlsession получает код ошибки 403. А также недействительное значение около 0 происходит, когда сериализация json получает html или другой код, отличный от объекта vald json.

Попробуйте удалить перенаправление с веб-службы.

0 голосов
/ 05 июня 2018

Ваш запрос должен быть таким, это просто демонстрационная версия, которую вы должны изменить, соответственно, согласно вашему требованию,

if let url = URL(string: "https://api.cryptonator.com/api/full/BTC-ETH") {
    var urlRequest = URLRequest(url: url)
    urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
    urlRequest.setValue("application/json", forHTTPHeaderField: "accept")
    urlRequest.httpMethod = "get"

    URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
        guard let data = data, error == nil else {
            print(error ?? "")
            return
        }
        do {
            let response = try JSONDecoder().decode(ResultResponse.self, from: data)
            print(response)
        } catch {
            print("catch error", error.localizedDescription)
        }
    }.resume()
} else {
    //Your else code
}

Ниже приведены два класса Codable,

struct Ticker: Codable {
    let base, target, price, volume: String
    let change: String
    let markets: [String]
}

struct ResultResponse: Codable {
    let ticker: Ticker
    let timestamp: Int
    let success: Bool
    let error: String
}

Как только вы позвоните, вы получите следующий вывод:

ResultResponse(ticker: Demo.Ticker(base: "BTC", target: "ETH", price: "12.67485919", volume: "", change: "-0.04568160", markets: []), timestamp: 1528180081, success: true, error: "")
0 голосов
/ 05 июня 2018

Измените строки кода, чтобы сделать это:

if let error = error {
    print(error.localizedDescription)
    return
 }
 if let httpResponse = response as HTTPURLResponse {
    if httpResponse.statusCode == 200 {
         // do your json deserialization after you verify you 
         // got a 200 / OK from the server
         do {
            if let data = data {
                let jsonData = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any]
                self.createCoinPairData(with: jsonData)
            } else {
                self.delegate?.updateInfoLabelContent(content: .noInternetConnection)
            }
        } catch {
            self.delegate?.updateInfoLabelContent(content: .error)
            print("catch error", error, data?.description as Any)
            self.retrieveCoinPairData()
        }
    } else {
        print("reponse /api/full", response)
    }
 }

И вы увидите, что вам следует пытаться десериализовать JSON, только если вы знаете, что сервер отправил вам ответ 200 / OK.

...