如何将非标准JSON的JavaScript对象字符串解析为可用对象?
处理非标准JS对象字符串的几种安全方法
这个问题挺常见的——处理半JSON半JS对象字面量的字符串确实头疼,既不能直接用JSON.parse,又不想碰有安全风险的eval。下面给你几个可行的方案,按实用性和安全性排序:
1. 使用JSON5库(最省心的方案)
JSON5是JSON的超集,专门兼容JS对象字面量的语法(比如无引号属性名、单引号字符串、尾逗号等),完全能解析你给出的这种字符串。
步骤:
首先安装依赖:
npm install json5
然后解析字符串:
const JSON5 = require('json5'); const inputStr = `{method: 'POST', url: '/iot/pipe/', query: {}, body: { d: '{"n": "861359031087669", "b": 100, "v": "02.37", "t": 1, "d":[[1515070895,413973366,21717600,110,1,0],[1515070897,413975033,21719083,102,1,0]]}' }, headers: { host: 'node_session_iot', connection: 'close', 'content-length': '1219', accept: '*/*', 'user-agent': 'QUECTEL_MODULE', 'content-type': 'application/x-www-form-urlencoded' } }`; // 直接解析成JS对象 let parsedObj = JSON5.parse(inputStr); // 注意:body里的d是一个嵌套的JSON字符串,需要再解析一次 parsedObj.body.d = JSON.parse(parsedObj.body.d); console.log(parsedObj);
优缺点:
- ✅ 无需手动处理语法兼容,适配绝大多数JS对象字面量场景
- ✅ 比
eval/Function安全很多 - ❌ 需要引入第三方依赖
2. 手动修正字符串为标准JSON(无依赖方案)
如果不想加依赖,可以通过正则把非标准的JS对象字面量转换成标准JSON,再用JSON.parse解析。核心是修复两个问题:给无引号的属性名加双引号,把单引号字符串改成双引号。
代码示例:
const inputStr = `{method: 'POST', url: '/iot/pipe/', query: {}, body: { d: '{"n": "861359031087669", "b": 100, "v": "02.37", "t": 1, "d":[[1515070895,413973366,21717600,110,1,0],[1515070897,413975033,21719083,102,1,0]]}' }, headers: { host: 'node_session_iot', connection: 'close', 'content-length': '1219', accept: '*/*', 'user-agent': 'QUECTEL_MODULE', 'content-type': 'application/x-www-form-urlencoded' } }`; // 步骤1:给无引号的属性名添加双引号 let fixedJson = inputStr.replace(/(\w+):/g, '"$1":'); // 步骤2:把不在双引号内的单引号替换成双引号(避免破坏嵌套的JSON字符串) fixedJson = fixedJson.replace(/'(?=(?:[^"]*"[^"]*")*[^"]*$)/g, '"'); // 解析外层对象 let parsedObj = JSON.parse(fixedJson); // 解析嵌套的d属性 parsedObj.body.d = JSON.parse(parsedObj.body.d); console.log(parsedObj);
优缺点:
- ✅ 零依赖,轻量
- ❌ 正则表达式的健壮性有限,如果字符串里有复杂场景(比如属性值含特殊字符)可能出错,需要根据实际情况调整正则
3. 使用Function构造函数(仅可控场景使用)
Function构造函数比eval安全一些(它在全局作用域执行,不会污染当前作用域),但仅当你完全信任输入内容时才能用——如果输入包含恶意代码,会被直接执行。
代码示例:
const inputStr = `{method: 'POST', url: '/iot/pipe/', query: {}, body: { d: '{"n": "861359031087669", "b": 100, "v": "02.37", "t": 1, "d":[[1515070895,413973366,21717600,110,1,0],[1515070897,413975033,21719083,102,1,0]]}' }, headers: { host: 'node_session_iot', connection: 'close', 'content-length': '1219', accept: '*/*', 'user-agent': 'QUECTEL_MODULE', 'content-type': 'application/x-www-form-urlencoded' } }`; // 构造一个返回目标对象的函数 const getObject = new Function(`return ${inputStr};`); let parsedObj = getObject(); // 解析嵌套的d属性 parsedObj.body.d = JSON.parse(parsedObj.body.d); console.log(parsedObj);
优缺点:
- ✅ 实现简单,无需依赖
- ❌ 存在安全风险,不可用于不可信输入场景
4. 使用AST解析器(高安全性方案)
如果对安全性要求极高(比如处理来自外部的不可信输入),可以用JavaScript解析器(比如acorn)把字符串解析成抽象语法树(AST),再手动遍历AST转换成对象。这种方式可以完全控制解析过程,过滤掉任何危险的语法(比如函数调用、赋值表达式)。
步骤:
首先安装依赖:
npm install acorn
然后解析AST并转换:
const acorn = require('acorn'); const inputStr = `{method: 'POST', url: '/iot/pipe/', query: {}, body: { d: '{"n": "861359031087669", "b": 100, "v": "02.37", "t": 1, "d":[[1515070895,413973366,21717600,110,1,0],[1515070897,413975033,21719083,102,1,0]]}' }, headers: { host: 'node_session_iot', connection: 'close', 'content-length': '1219', accept: '*/*', 'user-agent': 'QUECTEL_MODULE', 'content-type': 'application/x-www-form-urlencoded' } }`; // 解析字符串为AST const ast = acorn.parseExpressionAt(inputStr, 0); // 递归遍历AST,转换成JS对象 function astToValue(node) { switch (node.type) { case 'ObjectExpression': return node.properties.reduce((obj, prop) => { const key = prop.key.type === 'Identifier' ? prop.key.name : prop.key.value; obj[key] = astToValue(prop.value); return obj; }, {}); case 'Literal': return node.value; case 'ArrayExpression': return node.elements.map(astToValue); default: throw new Error(`不支持的节点类型: ${node.type}`); } } let parsedObj = astToValue(ast); // 解析嵌套的d属性 parsedObj.body.d = JSON.parse(parsedObj.body.d); console.log(parsedObj);
优缺点:
- ✅ 最高安全性,完全可控解析过程,可过滤危险代码
- ❌ 实现复杂,需要理解AST结构,代码量较大
内容的提问来源于stack exchange,提问作者Flame_Phoenix
相关产品推荐
相关产品推荐

