在JavaScript中用正则表达式对JSON字符串指定字段进行掩码处理
问题描述
我是NodeJS和正则表达式的新手,现有一段JSON字符串:
var jsonString = "[{\"ReturnCode\":0,\"TextID\":\"nwComputedSubTotal\",\"AccountNum\":\"958375845\",\"Status\":\"SomeStatus\"}]";
希望对数组var fieldsToMask = ['TextID', 'AccountNum', 'ReturnCode'];中指定的字段值用星号掩码,规则如下:
- 若字段在fieldsToMask数组中且值长度≥4,保留前2个字符,其余替换为星号;
- 若值长度≤3,则替换为3个星号;
- 不在数组中的字段值保持原样。
预期结果如下:
[{"ReturnCode":"***","TextID":"nw****************","AccountNum":"95*******", "Status":"SomeStatus"}];
我尝试编写了如下代码,但因正则表达式使用不熟练,无法正确转义双引号,导致没有任何字段被掩码:
var fieldsToMask = ['TextID', 'AccountNum', 'ReturnCode']; fieldsToMask.forEach(function (field) { var regex = new RegExp("\"" + field + ":" + "\"" + "(.*?)", "g"); jsonString = jsonString.replace(regex, function (match, p1) { if (p1.length > 3) { return field + ":" + p1.substring(0, 2) + "*".repeat(p1.length - 2); } else { return field + ":" + "***"; } }); });
解决方案
问题分析
你原来的代码存在两个核心问题:
- 正则匹配逻辑错误:既没正确匹配字段名与值的结构(比如忽略了数字值没有引号的情况),也没处理值的边界;
- 替换逻辑缺失:替换时没保留字段名的双引号,也没区分值的类型(字符串/数字)。
直接用正则操作JSON字符串很容易踩坑(比如值包含转义引号、逗号时会匹配失效),更稳妥的方式是先解析JSON为对象,处理后再转回字符串。
推荐实现代码
var jsonString = "[{\"ReturnCode\":0,\"TextID\":\"nwComputedSubTotal\",\"AccountNum\":\"958375845\",\"Status\":\"SomeStatus\"}]"; var fieldsToMask = ['TextID', 'AccountNum', 'ReturnCode']; // 1. 解析JSON为JS对象 const data = JSON.parse(jsonString); // 2. 遍历处理每个字段 data.forEach(item => { Object.keys(item).forEach(key => { if (fieldsToMask.includes(key)) { const valueStr = String(item[key]); // 统一转为字符串处理 item[key] = valueStr.length >= 4 ? `${valueStr.slice(0,2)}${'*'.repeat(valueStr.length - 2)}` : '***'; } }); }); // 3. 转回JSON字符串 const maskedJson = JSON.stringify(data); console.log(maskedJson);
输出结果
[{"ReturnCode":"***","TextID":"nw****************","AccountNum":"95*******","Status":"SomeStatus"}]
正则方式(不推荐,仅作参考)
如果一定要用正则实现,需要修正匹配规则和替换逻辑:
var fieldsToMask = ['TextID', 'AccountNum', 'ReturnCode']; fieldsToMask.forEach(field => { // 匹配带引号的字符串值或数字值 const regex = new RegExp(`"${field}":(?:(")(.*?)")|(\\d+)`, 'g'); jsonString = jsonString.replace(regex, (match, quote, strVal, numVal) => { const value = strVal || String(numVal); const masked = value.length >=4 ? `${value.slice(0,2)}${'*'.repeat(value.length-2)}` : '***'; // 保留字符串值的引号 return `"${field}":${quote ? `"${masked}"` : `"${masked}"`}`; }); }); console.log(jsonString);
注意:这种正则方式仅适用于简单JSON结构,若值包含转义引号、特殊字符会失效,仍推荐解析对象的方案。
内容的提问来源于stack exchange,提问作者Rocker2982
相关产品推荐
相关产品推荐

