You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用eval()解析JSON路径获取API价格时报语法错误的解决方法

问题:使用eval解析API响应路径时在数组索引场景下报错怎么解决?

我开发了一个从交易所API获取价格的部件,核心代码如下:

function getPrice(callback) {
  var Url = 'https://insert.api.url/';
  var Key = 'insert.json.key';
  request(Url, function(req) {
    var data = JSON.parse(req.responseText);
    var rate = eval("data." + Key);
    callback(rate);
  });
  return true;
}
function request(Url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = (function(xhr) {
    return function() {
      callback(xhr);
    }
  })(xhr);
  xhr.open('GET', Url, true);
  xhr.send();
}

这段代码在部分API中能正常工作,比如对接Kraken API时:

var Url = 'https://api.kraken.com/0/public/Ticker?pair=XBTUSD';
var Key = 'result.XXBTZUSD.c[0]';

但在使用CoinMarketCap API时会触发eval的“expected token”语法错误,此时的配置是:

var Url = 'https://api.coinmarketcap.com/v1/ticker/bitcoin/';
var Key = '0[price_usd]';

请问这种情况该如何解决?


回答

嘿,这个问题我之前也碰到过!核心问题出在eval拼接后的语法不合法,咱们一步步来拆解和解决:

为什么会报错?

当你用eval("data." + "0[price_usd]")时,实际执行的代码是data.0[price_usd]——这在JavaScript里是纯纯的语法错误:

  • 数字开头的属性/数组索引不能用点语法访问,得用方括号data[0]
  • 正确的访问方式应该是data[0].price_usd或者data[0]['price_usd']

而且eval本身就有安全风险(如果路径字符串被恶意篡改)和性能问题,完全没必要用它。

解决方案:自己实现路径解析函数

咱们写一个通用的函数,专门用来访问嵌套对象/数组里的属性,不管是点分隔还是括号语法都能处理:

function getNestedValue(obj, path) {
  // 先把[xxx]格式转换成.xxx,统一用点来分割路径
  const normalizedPath = path.replace(/\[(['"]?)([^'"]+)\1\]/g, '.$2');
  // 拆分路径成一个个片段
  const segments = normalizedPath.split('.');
  
  // 遍历片段,一层层访问嵌套结构
  return segments.reduce((current, segment) => {
    // 如果当前层级不存在,直接返回undefined避免报错
    if (current == null) return undefined;
    // 判断是不是数组索引(比如"0"这种数字字符串)
    const isArrayIndex = !isNaN(parseInt(segment)) && Number.isInteger(parseFloat(segment));
    return isArrayIndex ? current[parseInt(segment)] : current[segment];
  }, obj);
}

然后修改你的getPrice函数,用这个函数替代eval:

function getPrice(callback) {
  var Url = 'https://api.coinmarketcap.com/v1/ticker/bitcoin/';
  var Key = '0[price_usd]'; // 写成"0.price_usd"也能正常工作
  request(Url, function(req) {
    // 加个try-catch处理JSON解析失败的情况
    try {
      var data = JSON.parse(req.responseText);
      var rate = getNestedValue(data, Key);
      callback(rate);
    } catch (err) {
      console.error('解析数据失败:', err);
      callback(null); // 出错时给回调传null或者错误信息
    }
  });
  return true;
}

// 顺便给request函数加个请求成功的判断,避免处理错误响应
function request(Url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = (function(xhr) {
    return function() {
      // 只有请求完成且成功时才回调
      if (xhr.readyState === 4 && xhr.status === 200) {
        callback(xhr);
      }
    }
  })(xhr);
  xhr.open('GET', Url, true);
  xhr.send();
}

额外优化小贴士

  1. 让组件更通用:把Url和Key作为参数传入getPrice,这样不用每次修改函数就能对接不同API
  2. 增强容错性:在getNestedValue里可以加入更多错误处理,比如路径不存在时返回默认值
  3. 考虑用fetch替代XHR:现代浏览器支持fetch API,写法更简洁,还支持Promise,比传统XHR好用多了

这样修改后,不管是Kraken的result.XXBTZUSD.c[0]还是CoinMarketCap的0[price_usd],都能正确解析到对应的值,而且彻底摆脱了eval的各种坑。

内容的提问来源于stack exchange,提问作者yamahama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:34:13