Safely turning a JSON string into an object
技术背景
[JSON
][2] API 随着 ECMAScript 5 被引入,目前市场上超过 99% 的浏览器都实现了该 API。jQuery 曾经有一个 $.parseJSON()
函数,但在 jQuery 3.0 中已被弃用,实际上它长期以来只是 JSON.parse()
的包装器。
实现步骤
使用 JSON.parse()
方法
这是将 JSON 字符串转换为对象的纯 JavaScript 方法,只要确保使用的是较新的浏览器即可。示例代码如下:
1 2 3
| let jsonString = '{"city": "Boston", "population": 500000}'; let jsonObject = JSON.parse(jsonString); console.log(jsonObject.city, jsonObject.population);
|
处理异常情况
如果无法保证输入的字符串一定是有效的 JSON 格式,可以使用 try...catch
块来捕获可能的错误:
1 2 3 4 5 6 7
| let jsonString = '{"city": "Boston", "population": 500000}'; let data; try { data = JSON.parse(jsonString); } catch (error) { data = { message: 'Server error, please retry' }; }
|
使用 reviver
函数
可以使用 reviver
函数对解析结果进行过滤或转换:
1 2 3 4 5
| let jsonString = '{"city": "Boston", "population": 500000}'; let data = JSON.parse(jsonString, function reviver(key, value) { return value; });
|
核心代码
基本的 JSON.parse()
使用
1 2 3 4 5
| let jsonRes = '{ "students" : [' + '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' + '{ "firstName":"Richard" , "lastName":"Joe","age":20 }, ' + '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}'; let studentObject = JSON.parse(jsonRes);
|
安全解析函数
1 2 3 4 5 6 7 8 9 10 11 12 13
| JSON.safeParse = function (input, def) { if (!input) { return def || {}; } else if (Object.prototype.toString.call(input) === '[object Object]') { return input; } try { return JSON.parse(input); } catch (e) { return def || {}; } };
|
TypeScript 安全解析函数
1 2 3 4 5 6 7
| export function safeJsonParse(str: string) { try { return JSON.parse(str); } catch (e) { return str; } }
|
最佳实践
处理不同类型的数据
- 数组:当使用
JSON.parse()
解析从数组派生的 JSON 时,该方法将返回一个 JavaScript 数组。
1 2
| let myArr = JSON.parse('["apple", "banana", "cherry"]'); console.log(myArr[0]);
|
- 日期对象:JSON 中不允许使用日期对象,可以在解析后将字符串转换为日期对象。
1 2 3
| let text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}'; let obj = JSON.parse(text); obj.birth = new Date(obj.birth);
|
- 函数:JSON 中不允许使用函数,如果需要包含函数,可以将其写成字符串,解析后再使用
eval
转换。
1 2 3
| let text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}'; let obj = JSON.parse(text); obj.age = eval("(" + obj.age + ")");
|
深度克隆对象或数组
可以使用 JSON.stringify()
和 JSON.parse()
的组合来实现对象或数组的深度克隆。
1 2 3 4
| let arr2 = [1, 2, [3, 4]]; let newArrDeepclone = JSON.parse(JSON.stringify(arr2)); arr2[2][0] = 'changed'; console.log(newArrDeepclone);
|
常见问题
解析非有效 JSON 字符串
如果输入的字符串不是有效的 JSON 格式,JSON.parse()
会抛出 SyntaxError
异常。可以使用 try...catch
块来捕获并处理该异常。
性能问题
不同的解析方法在不同的浏览器和数据类型下性能有所不同。例如,eval/Function
方法在 Chrome 上对于小对象可能很快,但对于大的深层对象(N = 1000)可能会导致栈溢出错误;JSON.parse()
在 Safari 和 Firefox 上是最快的。可以参考 性能测试 了解更多细节。