JSON";字符“0”周围的值无效;尽管url工作完美,JSON是有效的

JSON";字符“0”周围的值无效;尽管url工作完美,JSON是有效的,json,swift,macos,api,urlsession,Json,Swift,Macos,Api,Urlsession,我有一个json错误,它似乎是随机出现的 我从域中加载json并将其解析到字典中。如果错误没有发生,它的工作将完美无缺。代码如下: func retrieveCoinPairData() { guard !checkIfBaseAndTargetAreEqual() else { return } if let base = self.currentBase, let target = self.currentTarget { if let url = URL

我有一个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
错误发生在
try JSONSerialization.jsonObject(带有:data,options:.allowFragments)中,如下所示![字符串:任意]

现在,每当出现这个错误时(它是完全随机的),当我在浏览器中检查url时,它就可以正常工作

我用jsonlint.com检查了json,它是有效的,没有使json需要分段的顶级对象,尽管该选项在过去似乎减少了错误

我知道代码403错误告诉我网站阻止访问,代码3840错误告诉我没有要解析的内容。我仍然想知道错误发生在哪里,为什么会发生


这是本例中使用的站点:

更改代码行以执行此操作:

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)
    }
 }

您看到的是,只有当您知道服务器向您发送了200/OK响应时,才应该尝试JSON反序列化。

url上的重定向有时会发生。你可以看到重定向,比如ohio.something,有时你会请求url。 发生重定向时,urlsession将获取错误代码403。 当json序列化获取html或vald json对象以外的其他代码时,也会出现0左右的无效值


尝试从Web服务中删除重定向

您的请求应该是这样的,这只是演示版,您必须根据您的要求进行相应的修改

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
}
下面是两个可编码的类

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: "")

我怀疑在发生
403
错误的情况下,您没有从服务器返回有效的json(相反,您得到的是纯文本错误响应)。在尝试反序列化数据之前,可以使用
print(\(String(data:data,encoding:String.encoding.utf8))”
打印数据。谢谢。它会打印“\r\n403禁止\r\n\r\n403禁止\r\n
nginx\r\n\r\n\r\n”,所以您是对的。你知道这是怎么回事吗?这是我力所能及的吗?让我头疼的是,当我在Browser中手动打开url时,它随时都会工作,但与往常一样,如果预期的类型是集合类型,则选项
.allowFragments
是毫无意义的。省略
选项
参数。为了解决这个问题,请处理回复代码。是的,你是对的,所以我联系了他们,他们说如果ip超过100次/分钟,网站将自动禁止ip(在短时间内)。这是有道理的,尽管我不会说我的应用程序通过测试达到了这一点。等待他们的另一个答复。谢谢。仍然抛出:reponse/api/full可选({URL:}{status code:403,headers{Connection=“keep-alive”;“Content-Encoding”=gzip;“Content-Type”=text/html;Date=“Tue,Jun 2018 05:00:02 GMT”;“keep-alive”=timeout=15;Server=nginx;“Transfer-Encoding”=Identity;Vary=“Accept-Encoding”})不过,我的问题是,在我的代码和工作url之间的某个地方出了问题,我不知道是什么,你能指出你在哪里找到
https://api.cryptonator.com/api/full
endpoint?我正在查看cryptonator.com的API文档,但在API的任何地方都看不到
full
。它就在“完整的股票代码”下面。我希望这是你的问题?好的,谢谢。我理解html是如何创建3840错误的。“删除重定向”是什么意思?我该怎么做呢?根据“您不需要自己处理重定向。NSURLSession及其任务将适当地处理重定向,包括cookie处理”。这听起来好像远程服务器没有提供一个有效的站点来重定向到。我刚刚给他们发了电子邮件,也许他们有答案。我认为重定向可能真的是个问题。现在调用url不会被重定向,同时运行应用程序不会抛出错误。现在,我正在等待他们重定向我(在浏览器中),如果应用程序崩溃,至少应该识别错误。您无法删除或处理重定向。这应该是在服务器端完成的。所以我联系了他们,他们说如果ip超过100次/分钟,网站会自动禁止(在短时间内)。这是有道理的,尽管我不会说我的应用程序通过测试达到了这一点。等待他们的另一个答复。
ResultResponse(ticker: Demo.Ticker(base: "BTC", target: "ETH", price: "12.67485919", volume: "", change: "-0.04568160", markets: []), timestamp: 1528180081, success: true, error: "")