JSReports渲染报错Unexpected token < in JSON at position 0 求助
JSReports
Unexpected token < in JSON at position 0 报错根因与修复 核心问题判断
你对报错的基础认知是对的:这个错误本质是JSON.parse接收到了以<开头的非JSON内容(绝大多数场景是HTML格式的错误响应页),但问题不在你接口返回的业务数据本身,出在数据跨进程传递给渲染引擎的序列化环节。
具体触发原因
- 你使用的
request库开启json:true配置后,回调拿到的body虽然和接口返回的JSON结构一致,但对象上可能附带库注入的隐藏属性、响应元数据引用,这类内容无法被jsreport渲染进程的结构化克隆逻辑正常序列化。 - jsreport的handlebars渲染用独立子进程运行,主进程传递
req.data到子进程时,序列化失败会返回HTML格式的内部错误页,内部resolveReferences.js模块拿到这个HTML字符串直接执行JSON解析,就会抛出你看到的错误。 - 你当前的代码没有校验接口HTTP状态码,如果接口偶发返回404/500的HTML错误页,也会触发一模一样的报错。
可直接落地的修复方案
替换原有content.js内容为以下版本:
// server side script fetching remote data and preparing report data source const request = require('request'); // call remote http rest api async function fetchCircleIn() { return new Promise((resolve, reject) => { const options = { url: 'http://localhost:5000/API/Meets/14/Events?ForCircleIn=true', method: 'GET', json:true }; request(options, function(error, response, body) { if(error){ console.log(error); reject(error); } else{ // 校验接口状态码,拦截HTML格式的错误响应 if (response.statusCode !== 200) { return reject(new Error(`接口请求异常,状态码:${response.statusCode}`)) } console.log(body); // 做一次纯JSON深拷贝,清除所有不可序列化的附加属性 const pureFormattedData = JSON.parse(JSON.stringify(body)) resolve(pureFormattedData); } }); }) } // add jsreport hook which modifies the report input data async function beforeRender(req, res) { let data = await fetchCircleIn(); console.log(data); req.data.Individuals = data; }
补充排查手段
如果替换代码后仍报错,直接打开本地报错栈指向的resolveReferences.js文件,在第4行的JSON.parse调用前加一行日志console.log('待解析原始内容:', arguments[0]),重新触发渲染后控制台会打印出实际被解析的内容:
- 如果打印内容是
<html>开头的错误页,直接看页面里的错误提示即可定位剩余问题,常见原因是模板引用的CSS资产路径错误、调用了不存在的助手函数、引用了不存在的局部模板。 - 如果打印内容是正常JSON,检查你模板里是否写了返回HTML字符串的自定义助手,被内部逻辑误当成配置引用解析。
内容的提问来源于stack exchange,提问作者GoldPaintedLemons
相关产品推荐
相关产品推荐

