JSON.stringify()和JSON.parse()不能转换RegExp的问题
Junan 2022-03-26
js
技巧
# 前言
有一个Json
对象如{"name": 'admin', "pattern": /^[0-9]+$/}
,用JSON.stringify()
转成Json
字符串的时候发现转成了"{"name":"admin","pattern":{}}"
,把正则对象转成了空对象。以至于调用JSON.parse()
时,把这条正则数据给丢失了。
# 原因
JSON.stringify
会处理的几种类型: String, Number, Boolean, null, Array, Object
不会处理的几种类型: Date, RegExp, undefined, Function
var o = {
n: 1,
s: 'abc',
b: true,
empty: null,
a: [1,2,3],
o:{ a: 1},
d: new Date(),
r: /abc/,
u: undefined,
f: function(){}
}
console.log(JSON.stringify(o));
// {"n":1,"s":"abc","b":true,"empty":null,"a":[1,2,3],"o":{"a":1},"d":"2018-07-05T02:49:37.194Z","r":{}}
可以看到,支持的类型都被处理了; 不支持的类型中,Date类型被转成了字符串输出,正则表达式转成了空对象, undefined
和Function
都被直接忽略了。
# 解决
用到JSON.stringify
方法中的第二个可选参数 replacer
。
如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的
Json
字符串中;如果该参数为null或者未提供,则对象所有的属性都会被序列化;
对于JSON.stringify
不支持的数据类型,推荐使用replacer
来处理。
JSON.stringify({r: /abc/}, function(k, v){
if(v instanceof RegExp){
return v.toString();
}
return v;
});
// '{"r":"/abc/"}'
同理,要将带有正则字符串的Json
字符串解析成Json
对象的时候,也要讲不支持转换的类型做处理,也要用到JSON.parse
的第二个参数。
JSON.parse(text[, reviver])
text:必需, 一个有效的 JSON 字符串。
reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
如:
JSON.parse('{"p": 5}', function(k, v) {
if (k === '') { return v; }
return v * 2;
});
JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', function(k, v) {
console.log(k); // 输出当前属性,最后一个为 ""
return v; // 返回修改的值
});
# 最后
附一个工具类
/**
* 解决JSON.stringify和JSON.parse不能转换RegExp的问题
* @author Junan
* @see JSON.parse();JSON.stringify()
*/
/**
* json字符串转json对象
* @param { String } jsonStr json字符串
*/
export function parseJson(jsonStr){
return JSON.parse(jsonStr, (k, v) => {
try{
// 将正则字符串转成正则对象
if (eval(v) instanceof RegExp) {
return eval(v);
}
}catch(e){
// nothing
}
return v;
});
}
/**
* json对象转json字符串
* @param { Object } json json对象
*/
export function stringifyJson(json){
return JSON.stringify(json, (k, v) => {
// 将正则对象转换为正则字符串
if(v instanceof RegExp){
return v.toString();
}
return v;
});
}