javascript - 格式化 JavaScript 对象占位符和替换对象
问题描述
我有一个带有占位符 ${var_name} 的对象
{
"name": "${title}",
"description": "${description}",
"provider": {
"@type": "Organization"
},
"hasInstance": [
{
"@type": "instance",
"mode": [
"study",
"online"
],
"offers": {
"@type": "Offer",
"price": "${price}"
}
}
]
}
和一个替换的对象
{
"title": "aaa",
"description": "bbb \n ccc",
"price": 100,
"history": "ddd"
}
替换占位符后,预期结果:
{
"name": "aaa",
"description": "bbb \n cc",
"provider": {
"@type": "Organization"
},
"hasInstance": [
{
"@type": "instance",
"mode": [
"study",
"online"
],
"offers": {
"@type": "Offer",
"price": 100
}
}
]
}
我的想法是:
- 将带有占位符的对象转换为字符串
- 然后用替换对象替换
- 再次将字符串转换为对象
问题是:JSON.parse
将失败,数据包含 JSON 转义,例如:"、\、/、\b、\f、\n、\r、\t
function replace(template, data) {
let templateString = JSON.stringify(template);
var placeholders = templateString.match(/\${([\w\.\:]+)}/g);
placeholders.forEach(placeholder => {
// convert ${var_name} to var_name, then assign to phText
let phText = placeholder.substring(2,placeholder.length - 1);
if(data[phText]) {
templateString = templateString.replace(placeholder, data[phText]);
}
});
return JSON.parse(templateString);
}
解决方案
在不解析 JSON 的情况下,递归扫描对象,搜索占位符模式,并将其替换为新值:
function scanObjectAndReplace(newValues, obj, key=false){
if(key && typeof(obj[key])==='string'){
let str = obj[key];
let i1=str.indexOf("${");
let i2=str.indexOf("}");
if(i1>=0 && i2>i1) {
let keyname = str.substring(i1+2, i2);
let substr = str.substring(i1, i2+1);
if(!(keyname in newValues)) {console.log(`key ${keyname} not exist in new valuse.`);return}
if(i1==0 && i2==str.length-1) // if value include only the placeholder then set a new value
obj[key] = newValues[keyname];
else
obj[key] = str.replace(substr,values[keyname]); // otherwise treat it as string replacment
console.log(`oldval=${str}, newval=${obj[key]}, type=${typeof(obj[key])}`)
}
} else {
let objval = key ? obj[key] : obj;
if (Object.keys(Object(objval)).length>0) {
for (const k of Object.keys(objval)){
console.log(k);
scanObjectAndReplace(newValues,objval, k);
}
}
}
}
scanObjectAndReplace(new_values, obj); // call the function
您可以将 regexp 用于较短的版本,但我的函数更易于调试。
推荐阅读
- r - 如果间隙超过特定时间,则查找持续时间并创建阈值
- c# - 如何使用 foreach 在 Razor 中设置 Viewbag 值?
- java - 依赖注入:应该先做哪个?属性(字段)或依赖项?
- python - Python 类:在将 True 切换为 False 时无法增加自维护以来的行程计数器,也无法在修复后将计数器重置为零
- svelte - 使用 Svelte 没有箭头函数的复选框验证
- c++ - C++ - unordered_map 运算符 [],意外行为
- python - 在 Python 程序中循环我的 IF 语句
- git - 尝试从 ghithub 进行 git clone 时出现 HTTP 407
- wpf - 在 XAML 中创建组合框时如何在 PowerShell 中显示数组中的选项
- prolog - 我想使用 Prolog 来订购一些东西,但我不断收到堆栈溢出错误