注册
web

她说:JSON 没错,但就是 parse 不过?我懂了!


技术纯享版:《不规范 JSON 怎么办?三种修复思路+代码实现》



开篇:夜色渐浓,佳人亦在


那天晚上,办公室的灯已经灭了大半,只剩几个工位发出轻轻的蓝光。中央空调早就熄了,但显示器的热度依然在屏幕前形成一圈圈淡淡的光晕。


我坐在靠窗的位置,刚把代码提交推送完,正打算收键盘走人。


这时,小语走过来,端着还冒着热气的速溶咖啡——她果然又是那个留下来最晚的人之一。


“诶~”她蹲在我旁边的桌子边上,语气带着一丝挫败,“你这边有没有遇到 JSON 字符串明明格式看着没错,却死活 JSON.parse 不过的情况?”


一个普通的错误,却不是普通的崩溃


原来她在调试一个用户日志上传模块,前端接收到的日志数据是从后端来的 JSON 字符串。


问题出在一个看似再平常不过的解析操作上——


const logData = JSON.parse(incomingString);

可是控制台总是报错:Unexpected token。数据一眼看去也没问题,{'name': 'Tom', 'age': 30} —— 结构清晰,属性齐全,但偏偏就是“坏掉了”。


她抿了一口咖啡,苦笑,“我知道是引号的问题,可这种数据是从破旧的系统里吐出来的,量还特别大,我不可能一个个手动改。”


风起 · JSON.parse 不是万灵药


我们一起回顾了她的实现方式。她用的是最基础的 JSON.parse(),这是我们在项目里默认的处理方式——简单、直接、快速。


但这个方法对 JSON 格式的要求极其严格:



  • 只能使用双引号 "
  • 属性名必须加引号
  • 不容忍任何额外字符或注释

一旦出现诸如单引号、缺少逗号、多余空格这些“微小过失”,就直接抛错了。


小语叹气,“很多时候这些 JSON 是设备端拼出来的,不规范,又没有错误提示,我根本不知道该怎么修。”


我翻了翻之前的代码,从夹缝中找出来一张破旧的黄皮纸,我们俩一起瞅了上去,看到上面写着


function tryParseJSON(jsonString) {
try {
return JSON.parse(jsonString);
} catch (e) {
// 尝试简单修复:去除可能的多余字符
const cleaned = jsonString.replace(/[^\x20-\x7E]/g, '').trim();
try {
return JSON.parse(cleaned);
} catch (e2) {
console.error("无法解析JSON:", e2);
return null;
}
}
}

下面备注了一行小字:此法在一些更轻量的场景里,做一些“简陋修复“,对于简单的问题有时能奏效,但对于更复杂的错误,比如混合了单引号和双引号的情况,只能再实现另一个方法可以做更针对性的修复方法


function fixQuotes(jsonString) {
// 将单引号替换为双引号(简单情况)
return jsonString.replace(/'/g, '"');
}

小语感叹一声:“没有更好的了吗?”


解决篇 · 来自大佬的一句话


恰好这时,阿杰从会议室出来,耳机还挂在脖子上。


他听了一耳朵后随口说了句:“你们试过 jsonrepair 吗?那玩意能把坏 JSON 修回来,就像修车。”


“json... repair?”小语一脸困惑。


我忽然想起,之前有个日志监控服务也碰到类似的问题,当时就是用了这个库一把梭。


我打开编辑器,快速翻出来了这一段:


npm install jsonrepair

const { jsonrepair } = require('jsonrepair');

const damaged = "{name: 'John', age: 30}";
const fixed = jsonrepair(damaged); // => {"name":"John","age":30}
const obj = JSON.parse(fixed);

小语凑过来看了一眼,眼睛一亮:“它真的把引号补好了?”


我点头。这个工具是为了解决类似“非标准 JSON”问题的,它会尽可能地补全缺失引号、逗号,甚至处理 Unicode 异常字符。


当然,也不是所有情况都适用。


比如碰到乱码或者非法嵌套结构,jsonrepair 有时也会无能为力。这时可以退一步——用更宽松的解析器,比如 JSON5


const JSON5 = require('json5');
const result = JSON5.parse("{name: 'John', age: 30}"); // 也能解析

我看着认真学习的小语,语重心长的讲道:它不是修复,而是扩展 JSON 标准,让一些非标准写法也能解析(JSON5 能容忍的内容包括:单引号、尾逗号、注释、未加引号的属性名、十六进制、科学计数法等数字格式)


接着我们还讨论了更复杂的修复方式,比如用正则处理批量日志,甚至用 AST 工具逐步构建 JSON 树。但那是更远的故事了。


面对当前的问题,我们准备搞一套组合拳:


function parseJson(jsonString) {
// 第一步:尝试标准JSON解析
try {
return JSON.parse(jsonString);
} catch (e) {
console.log("标准JSON解析失败,尝试修复...");

// 第二步:尝试使用jsonrepair修复
try {
const { jsonrepair } = require('jsonrepair');
const fixedJson = jsonrepair(jsonString);
return JSON.parse(fixedJson);
} catch (e2) {
console.log("修复失败,尝试使用JSON5解析...");

// 第三步:尝试使用JSON5解析
try {
const JSON5 = require('json5');
return JSON5.parse(jsonString);
} catch (e3) {
// 最后:如果所有方法都失败,返回错误信息
console.error("所有解析方法都失败了:", e3);
throw new Error("无法解析JSON数据");
}
}
}
}

结局


一段时间后,小语在前端监控日志里贴了段截图:原本一天上千条的 parse error 错误,几乎消失了。


她补了一句:“终于不用再一个个点开调日志了。”


我回头看她的工位,屏幕亮着,浏览器里是一个模拟器页面,console 正在缓缓输出内容。


她突然抬起头看着我,问道:“AST是什么?听说也能实现json修复?”


作者:洛小豆
来源:juejin.cn/post/7506754146894168118

0 个评论

要回复文章请先登录注册