问题
我们在Typescript/Javascript
中要将一个JSON
字符串解析为JSON对象
,一般会采用JSON.parse
。如果追求解析性能,在Nodejs
中也可能会使用一些第三方的库。但是在很多场合,我们会更在意容错性,比如:
`{
username:"fisher",
password:'123",
age:18,
}`
如果使用JSON.parse
解析上述字符串,则会出错。因为JSON.parse
只能解析严格的JSON
字符串,要求所有Key
必须使用"..."
包裹,未尾不能有,
等,规范比较严格。在某些场合就比较麻烦,我们希望解析能更加智能此,能处理一些非标问题,比如:
key
和value
可以混合使用"..."
或'...'
包裹- 能处理尾部的
,
等 - 处理一些无意中混入的中文全角符号
思路
第1步:匹配未添加逗号的行
使用以下正则表达式匹配行未添加正则表达式
const addLineCommaRegex = /(?<!(\s*\,\s*)|([\[\{\}]\s*))\n(?!\s*\}\s*)/gm;
let resultStr = str.replaceAll(addLineCommaRegex, ",\n");
第2步:匹配使用""或’'包裹字符串
使用正则表达式使用"..."
或'...'
包裹字符串,然后使用endcodeURI
进行编码。编码的目的是因为"..."
或'...'
内部可能包含一系列的符号或转义符等不利于进行后续的正则匹配。
const strVarRegex = /((?<!\\)\"|\')(.*?)((?<!\\)\1)/gm;
resultStr = resultStr.replaceAll(strVarRegex, (s, begin, value, end) => {
return `\"${encodeURI(value)}\"`;
});
第3步:为没有"…“包裹key加上”…"
const badKeyRegex = /([\s\[\,\{\b]{1})(?<!\"])(\w+)(?!\")(\s*\:)/gm;
resultStr = resultStr.replaceAll(badKeyRegex, (s, p1, value, p2) => {
return `${p1}\"${value}\"${p2}`;
});
第4步:将一些全角字符转换为半角字符
将一些全角字符转换为半角字符,同时使用decodeURL
进行解码恢复。
resultStr = resultStr.replaceAll(",", ",").replaceAll("“", '"').replaceAll("”", '"');
return JSON.parse(resultStr, (key, value) => {
if (typeof value == "string") value = decodeURI(value);
if (callback) {
return callback(key, value);
}
return value;
});
小结
完整函数请访问FlexTools
以下是我的一大波开源项目推荐:
- 全流程一健化React/Vue/Nodejs国际化方案 - VoerkaI18n
- 无以伦比的React表单开发库 - speedform
- 终端界面开发增强库 - Logsets
- 简单的日志输出库 - VoerkaLogger
- 装饰器开发 - FlexDecorators
- 有限状态机库 - FlexState
- 通用函数工具库 - FlexTools
- 小巧优雅的CSS-IN-JS库 - Styledfc
- 为JSON文件添加注释的VSCODE插件 - json_comments_extension
- 开发交互式命令行程序库 - mixed-cli
- 强大的字符串插值变量处理工具库 - flexvars
- 前端link调试辅助工具 - yald
- 异步信号 - asyncsignal