Skip to main content

手写 JSON.stringify / parse

手写 JSON.stringify

要点(也是面试爱问的边界):

  • undefined、函数、Symbol:作为对象值会被忽略,作为数组项变成 null,作为顶层值返回 undefined
  • NaNInfinitynull 都序列化为 "null"
  • 对象若有 toJSON 方法,序列化其返回值(如 Date
  • 不处理循环引用(原生会抛错)
function jsonStringify(data) {
const type = typeof data;

if (data === null) return "null";

if (type === "number") {
return Number.isFinite(data) ? String(data) : "null"; // NaN/Infinity -> null
}
if (type === "boolean") return String(data);
if (type === "string") return `"${data}"`;

// 顶层的 undefined / function / symbol 返回 undefined
if (type === "undefined" || type === "function" || type === "symbol") {
return undefined;
}

if (type === "object") {
// Date 等带 toJSON 的对象
if (typeof data.toJSON === "function") return jsonStringify(data.toJSON());

if (Array.isArray(data)) {
const items = data.map((item) => {
const v = jsonStringify(item);
return v === undefined ? "null" : v; // 数组里的 undefined/function -> null
});
return `[${items.join(",")}]`;
}

// 普通对象:忽略值为 undefined/function/symbol 的键
const items = [];
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
const v = jsonStringify(data[key]);
if (v !== undefined) items.push(`"${key}":${v}`);
}
}
return `{${items.join(",")}}`;
}
}

jsonStringify({ a: 1, b: undefined, c: [1, undefined, () => {}], d: null });
// => {"a":1,"c":[1,null,null],"d":null}

手写 JSON.parse

最简单的方式是借助 new Function(生产环境有 XSS 风险,仅作演示):

function jsonParse(str) {
return new Function("return " + str)();
}

严谨实现需要写一个递归下降解析器(词法分析 + 语法分析),逐字符扫描处理 {}/[]/字符串/数字/字面量。面试中能说清「为什么不能直接 eval」「如何做状态机解析」即可。