JSON String 格式化函数
2023-12-20 10:55 前端小白的江湖路 阅读(433) 评论(0) 编辑 收藏 举报背景
一般我们格式化JSON string是通过JSON.parse, 再使用JSON.stringify方法进行格式化,但是JSON.parse 有BigInt精度丢失问题
方案
考虑用以下纯字符串的方式来解析,添加空格与\n来缩进。
比较易漏的点在于
1.考虑转义字符,
2.字符串内的字符,不需要格式化,需要优先跳过。
/** * * @param jsonStr {string} JSON字符串格式化函数,去除多余的空格,\n等 * @param indentChar {string} 缩进字符,默认为2个空格缩进 * @returns string */ export const jsonPrettier = (jsonStr = "", indentChar = " ") => { if (typeof jsonStr !== "string") { console.warn(`jsonStr: ${jsonStr} 需要为字符串类型`); return jsonStr; } if (typeof indentChar !== "string") { throw new Error(`indentChar: ${indentChar}缩进字符需要为字符串类型`); } let result = ""; let isInString = false; // key, value, array子项 const SPACE_CHAR = " "; const ESCAPE_CHAR = "\\"; let indentLevel = 0; let i = 0; while (i < jsonStr.length) { const item = jsonStr[i]; // 跳过非字符串内的转义字符 if (item === "\n" || item === "\t" || item === "\r" || item === "\b") { i++; continue; } // 字符串内存在转义字符 if (item === ESCAPE_CHAR) { const nextChar = jsonStr[i + 1] ?? ""; result += item + nextChar; i += 2; continue; } if (item === '"') { result += item; isInString = !isInString; i++; continue; } if (isInString) { result += item; i++; continue; } // 不在string中 switch (item) { case SPACE_CHAR: i++; continue; case "{": case "[": result += `${item}\n`; indentLevel += 1; result += indentChar.repeat(indentLevel); break; case "}": case "]": result += "\n"; indentLevel -= 1; result += indentChar.repeat(indentLevel) + item; break; case ",": result += item + "\n"; result += indentChar.repeat(indentLevel); break; case ":": result += item + SPACE_CHAR; break; default: result += item; } i++; } return result; }; const test = (jsonStr = "") => { const a = JSON.stringify(JSON.parse(jsonStr), null, 2); const b = jsonPrettier(jsonStr); console.warn("is equal: ", a === b); console.log(`origin jsonStr: `, jsonStr); console.log("prettier result: ", b); console.log("----------"); if (a !== b) { throw new Error("a与b不相等"); } }; // number string boolean array object null undefined test("100 "); test("true "); test('"abc " '); test('{"a": 10, "b": 100}'); test('["a", "b", "{abcd}\\""]'); test('{ \r "a": 1, "b,,,": \n"bb: b", "c": { "d": 100,\n "e": "abc\\n"}}\n'); test( `{ \r "a": 1, "b,,,": \n "bb: b", "c": \t \t { "d": 100,\n "e": "abc\\n"}}\n` ); test(`{ "a": "a b c" }`);
输出结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通