【问题标题】:C++ Json parsing issue throws Unhandled ExceptionC++ Json 解析问题抛出未处理的异常
【发布时间】:2022-12-07 06:15:57
【问题描述】:

`` 我正在尝试按照其市值排名订购要交易的代币向量。它可以完美编译并运行,但在运行时抛出错误 3。代码在下面找到。

调试:json.hpp 抛出未处理的异常 MyProgram.exe 中 0x0000500000000000 处的未处理异常:Microsoft C++ 异常:内存位置 0x000000E000000000 处的 nlohmann::json_abi_v3_11_2::detail::type_error。

JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));

期望的结果:在从 api 请求市值排名后,将我的硬币向量从最高市值排序到最低。并列出终端的向量。

交易.cpp

#include <string>
#include <iostream>
#include <vector>
#include <cpr/cpr.h>
#include <nlohmann/json.hpp>
#include "trading.h"

// for convenience
using json = nlohmann::json;

using namespace cpr;
using namespace std;


//orders the coins from 1-20 ascending order
void trading::order(){
    //variables
    vector<string> coinsCopy;
    int rankOrder = 0;

    //order coing by market cap
    string base = "https://api.coingecko.com/api/v3/search?query=";
    string id;

    //makes a copy of coins
    for (int k = 0; k < coins.size(); k++) {
        coinsCopy.push_back(coins[k]);
    }


    for (int i = 0; i < coins.size(); i++) {
        //loop variables
        string id = coins[i];
        auto search = Get(Url{ base + id });
        json data = json::parse(search.text);

        //collects rank 
        for (json& item : data["coins"]) {
            rankOrder = item["market_cap_rank"];
            if (rankOrder > coins.size()) {
                rankOrder = coins.size();
            }
            break;
        }

        //updates coins to correct order in coins copy
        coinsCopy.at(rankOrder) = coins[i];
    }

    //updates main coin vector with correct rank order
    for (int ii = 0; ii < coins.size(); ii++) {
        coins.at(rankOrder) = coinsCopy[ii];
    }
}

void trading::listOrder() {
    for (int j = 0; j < coins.size(); j++) {
        cout << "Coin Ranked # " << j << ": " << coins[j] << endl;
    }
}

主.cpp

#include <cpr/cpr.h>
#include <iostream>
#include <nlohmann/json.hpp>
#include <string>
#include <vector>
#include "trading.h"

// for convenience
using json = nlohmann::json;

using namespace cpr;
using namespace std;


int main() {
    
    trading trade;

    
    trade.order();
    trade.listOrder();
    
}

JSON 文件样本

{"coins":[{"id":"bitcoin","name":"Bitcoin","api_symbol":"bitcoin","symbol":"BTC","market_cap_rank":1,"thumb":"https://assets.coingecko.com/coins/images/1/thumb/bitcoin.png","large":"https://assets.coingecko.com/coins/images/1/large/bitcoin.png"},

【问题讨论】:

  • 请将您的代码缩减为minimal reproducible example。正如消息告诉您的那样,您正在尝试将某些内容解析为不是数字的数字。通过删除部分,应该不难找出 JSON 的哪一部分导致了这种情况。此外,您程序中的很多内容与解析问题无关并阻碍了可重复性(例如,用文字中的测试 JSON 替换查询)。
  • 那么,您是否尝试过使用调试器单步执行代码以了解抛出异常的原因?
  • json 数据 = json::parse(search.text); //这是抛出异常的地方。为什么在上面的实际问题中列出。

标签: c++ nlohmann-json coingecko


【解决方案1】:

有许多带有null“market_cap_rank”的代币,例如目前是“xi-token”。 库无法将 null rank 转换为整数值。 问题是由于缺乏数据验证造成的。

另请注意,代码

vector<string> coinsCopy;
//...
for (int k = 0; k < coins.size(); k++) {
    coinsCopy.push_back(coins[k]);
}
//...
if (rankOrder > coins.size()) {
    rankOrder = coins.size();
}    
//...
coinsCopy.at(rankOrder) = coins[i];

根据实际的 rankOrder 值抛出。

编辑

我觉得有必要通过添加缺失的细节来使我的答案更加详尽。

通过下面的Python3脚本,我们得到了按“market_cap_rank”升序排列的前20个币种。

import requests
import json
import operator

def receive_coins():
    resp = requests.get(r'https://api.coingecko.com/api/v3/search')
    with open("response", 'w', encoding = 'utf-8') as response:
        response.write(resp.text)
        
def get_top20():    
    with open('response', 'r', encoding = 'utf-8') as response:
        jresp = json.load(response)
        coinlist = [
            (coin['id'], coin['market_cap_rank']) for coin in jresp['coins'] if coin['market_cap_rank']
        ]        
        return sorted(coinlist, key=operator.itemgetter(1))[:20]
    return []

print(get_top20())

他们是

[('bitcoin', 1), ('ethereum', 2), ('tether', 3), ('binancecoin', 4), ('usd-coin', 5), ('binance-usd', 6), ('ripple', 7), ('dogecoin', 8), ('cardano', 9), ('matic-network', 10), ('polkadot', 11), ('staked-ether', 12), ('litecoin', 13), ('shiba-inu', 14), ('okb', 15), ('dai', 16), ('solana', 17), ('tron', 18), ('uniswap', 19), ('avalanche-2', 20)]

“market_cap_rank”值的范围从 1 到 20,而不是从 0 到 19。 从问题陈述中,我们推断coinsCopy数组中恰好有20个元素,这证明了我的第二点,即coinsCopy.at(rankOrder) = coins[i];这一行抛出了异常。

另一个问题源于缺乏数据验证。 auto search = Get(Url{ base + id }); 行以可忽略的间隔重复了 20 次。 这可能会触发站点保护,从而导致收到特定于站点的意外响应。 在任何情况下都不会验证响应内容。

【讨论】:

  • 好吧,请求应该只获得我指定的硬币的市值排名,这些硬币目前都在前 20 名中。而且我还检查了主要的每一个,似乎显示了正确的市值排名。此外,我只从 json 数据中获取第一个市场排名然后打破。
  • @CraigForbes 请在此处发布coins 的内容。它看起来像是唯一缺失的部分。
  • @CraigForbes 您还可以通过编辑问题来提供“trading.h”文件的内容。
猜你喜欢
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
  • 2013-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多